DOM

元素节点的获取

要想对dom元素进行操作,必须先获取到这个节点,才能进行操作

获取元素的三种方式

 <body>
    <button id="btn">点击</button>
    <div class="item"></div>
    <a href="#">超链接</a>
  </body>
  <script>
    // 通过元素唯一的id来获取元素   id是唯一的
    var btn = document.getElementById("btn");
    console.log(btn);
    //通过元素的类名  来获取此节点
    var item = document.getElementsByClassName("item");
    console.log(item);
    //通过获取标签名  把节点取出来
    var alink = document.getElementsByTagName("a");
    console.log(alink);
  </script>

既然方式二、方式三获取的是标签数组,那么习惯性是先遍历之后再使用

特殊情况:数组中的值只有1个。即便如此,这一个值也是包在数组里的。这个值的获取方式如下:

 <body>
    <div class="item">你好</div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </body>
  <script>
    // 获取所有div中的第一个div
    var div = document.getElementsByTagName("div")[0];
    console.log(div);
  </script>

事件对象的内部的this

在事件对象的内部,有一个this,它指向的是事件源

  • this的指向,谁触发的事件,谁调用的,this就指向谁

不同函数内部this的指向

  1. 普通函数 ----------------> window对象
  2. 构造函数 -----------------> 指向的是生成的实例对象
  3. 对象的方法 --------------> 指向的是对象本身
  4. 事件函数 -----------------> 指向的是事件源
显示隐藏
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <style>
    #item {
      width: 200px;
      height: 200px;
      background-color: pink;
    }
  </style>
  <button>显示</button>
  <div id="item"></div>
</body>
<script>
  //获取元素
  var btn = document.querySelector('button');
  var item = document.getElementById('item');
  //定义变量,控制显示隐藏
  var num = 1;
  btn.onclick = function () {
    if (num === 1) {
      //当num的值为1的时候点击按钮将div隐藏,再将按钮内部的文字替换掉
      this.innerText = '隐藏';
      item.style.display = 'none';
      num = 2;
    } else {
      this.innerText = '显示';
      item.style.display = 'block';
      num = 1;
    }
  }
</script>

</html>
相册案例
  • 过程
    1. 获取元素(事件源。谁触发的事件)
    2. 给获取的元素添加点击事件,用for循环遍历,给每一个超链接添加点击事件
    3. 更改img内部src属性值,使用this,指向事件源
    4. 更改p标签内部的文字内容;
    5. 取消a标签的跳转
<body>
  <h2>城市街道</h2>
  <div class="so">
    <a href="img/1.jpeg" title="街道1">
      <img style="width:100px" src="img/001.jpeg" alt="">
      </a>
    <a href="img/2.jpeg" title="街道2">
      <img style="width:100px" src="img/002.jpeg" alt="">
      </a>
    <a href="img/3.jpeg" title="街道3">
      <img style="width:100px" src="img/003.jpeg" alt="">
      </a>
    <a href="img/4.jpeg" title="街道4">
      <img style="width:100px" src="img/004.jpeg" alt="">
      </a>
  </div> 
  <div class="bg ">
    <img id="imgs" src="" alt="">
    
  </div>
  <p>请选择图片</p>
</body>
<script>
  //获取元素
  var so = document.querySelector('.so');
  var aLi'[;.nks = so.getElementsByTagName('a');
  var imgs = document.getElementById('imgs');
  var txt = document.querySelector('p');
  //遍历数组。添加点击事件
  for(var i = 0; i < aLinks.length; i++){
      aLinks[i].onclick = function(){
        //更改img的内部的src的属性值
        imgs.src = this.href;
        //更改p标签内部的文字的内容
        txt.innerHTML = this.title;
        return false;
      }
  }
</script>

DOM里面取消a标签跳转默认效果

return false;

在事件函数内部书写这个语句

for循环内部添加的绑定事件,在触发时,所有添加的事件已经添加成功了,触发事件时是循环之后在触发的事件

批量绑定的事件函数的内部,如果有变量i, 注意,函数执行是已经是循环结束后

循环内部定义的变量是一个全局变量,在循环后执行的I变量的值I跳出循环的值

使用this来获取a标签内部的href属性,this的指向,是触发事件的事件源

获取标签内部的内容innerText,innerHTML

对比使用场景

  • innerText:在设置纯文本,不包含标签
  • innerHTML:在设置有子标签解构的时候使用,在设置的时候也可以在内部写html标签
  • innerHTML设置属性是,会按照html的语法中的标签加载
 var div = document.querySelector('div');
  console.log(div);
  div.innerHTML = '<h2>你好ya</h2>'

表单元素属性

属性 含义z
value 获取大部分表单内容,除了option以外
type 可以获取input标签类型
disabled 禁z
checked 复选框
selected 下拉菜单

!!注意,在DOM中对象的属性值只有一个时候,或被转换成布尔值,属性名与属性值相同。可以直接赋值为true

验证表单案例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .gr{
      border: 5px solid green;
    }
    .re{
      border: 5px solid red;
    }
  </style>
</head>
<body>
  <input type="text" id = "name">
  <input type="password" id = "password">
  <input type="button" id = "btn" value="提交">
</body>
<script>
  //检测用户输入的用户名是否是3-6位,密码是否是6-8位,要是不满足,需要高亮显示输入框


  //获取元素
  var text = document.getElementById('name');
  var password = document.getElementById('password');
  var btn = document.getElementById('btn');
  btn.onclick = function() {
    //用户名
    if(text.value.length < 3 || text.value.length > 6){
      text.className = 're';
      //如果他不成立就不要再进行下一步
      return;
    }else{
      text.className = 'gr';
    }
    if(password.value.length < 6 || password.value.length > 8){
      password.className = 're';
      //如果他不成立就不要再进行下一步
      return;
    }else{
      password.className = 'gr';
    }
    console.log('提交成功');
  }
</script>
</html>

随机下拉菜单案例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <button>选择</button>
  <select id="name">
    <option>拉面</option>
    <option>牛肉面</option>
    <option>安徽板面</option>
    <option>兰州拉面</option>
    <option>大碗宽面</option>
    <option>担担面</option>
  </select>
</body>
<script>
  //获取元素
  var btn = document.querySelector('button');
  var select = document.getElementById('name');
  var option = select.querySelectorAll('option');
  btn.onclick = function(){
    //随机选择option  每次点击需要获取一个数组随机下标
    //定义一个接收随机数的变量;
    //运用math对象里面的向上取整与随机生成数字的方法,来获取随机值 在乘以随机的值的长度,就可以得到一个在0-5之间的随机数
    var p = Math.floor(Math.random() * option.length);
    //随机出来的数对应html 里的option下标值
    select[p].selected = true;
    //在这里,dom里面,表单这一块,属性名与属性值名字相同,返回的值是true,不写是false 或者是空,
    //他的这个可以是true,要是一户参与其他程序,方便使用
  }
</script>
</html>

在使用math对象里面的random方法是,他生成的是【0,1)之间的数字 ,左边是闭区间,右面是开区间,设置随机生成数字就是方法乘以他的长度,就可以随机出0-5之间的随机数,更好的写法就是 random() * opts.length的长度 当一个选项删除会这是增加一项,就不会再次更改代码

搜索框案例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .bg{
      color:black;
    }
    .gr{
      color: gray;  
    }
  </style>
</head>
<body>
  <input type="text" id = "text" value="请输入用户名">
  <button>点击按钮</button>
</body>
<script>
 //获取元素
 var text = document.getElementById("text");
 //获取焦点   要是内容为空,那么文字是灰色的
 text.onfocus = function() {
    if( text.value == '请输入用户名' ){
      text.className = 'bg';
      text.value = '';
    }
 }
 //失去焦点  
 text.onblur = function() {
   //如果用户书写的整好是value的值,为了保证用户的视觉体验,
   //需要在添加一个条件就是当内容和value值相同时候,文字变成灰色

    if(text.value == '' || text.value =='请输入用户名'){
      text.value = '请输入用户名';
      text.className = 'gr'
    }
 }


</script>
</html>

自定义属性

元素自定义的属性是不可以通过点的形式来调用

  • 1 getAttribute('属性')
<!-- 在这里data-index是自定义属性值 -->
<div data-index="1"></div>
var div = document.querySelector("div");
console.log(div.getAttribute("data-index"));
  • 2 设置元素属性值 (针对自定属性值)
// 括号里面的值是  自定义属性名  属性值
div.setAttribute("data-index", 2);

这里自定义属性setAttribute里面的值,如果是添加的是class这个名字,不需要将他更改,因为里面的值是字符串类型的,与js内部定义好的值是不冲突的,所以不需要更改名字

  • 3 移除属性值 removeAttribute('自定义属性值')
div.removeAttribute("data-index");

在之后书写代码上,如果是定以过的属性,尽量去使用点取调用,而自定义的属性使用到的是他们三个

style样式属性操作

得到的值是行内样式,只能获取的是行内的样式,外联的样式不可以获取到的

补充:在获取元素时候,我们可以将获取元素的方法封装到函数里面,放在公共文件内,在使用时候,直接调用函数就可以了

function my$(id){
    return document.getElementById(id)
}
var btn = my$('btn')

上面个封装的是获取元素id的函数,通过调用函数传入id,可以实现获取元素,通过id的方式

  • 类似background-color 这样单一复合的属性,需要通过使用驼峰命名的方法第二个单词首字母大写
  • 在通过style属性设置行内样式的时候,值的类型是字符串,需要在后面加上px单位

样式操作的选择(何种方式)

实际工作中改如何选择设置样式的方法

  1. 很多个样式需要进行设置,就会选择使用class类名的方式进行更改
  2. 一条或者是两条css样式,可以通过行内的方式进行操作

js里面单独获取body 通过document.body的方式来获取body标签

切换案例的思路

两种方式

  1. 没办法通过全等或者是相等的判断,可以定义一个变量来进行管理
  2. 如果可以通过全等或者是相等的条件进行判断,可以直接使用全等/相等进行书写,减少代码量,减少定义变量

排他思想

在对批量添加只让自己做什么事情的时候,可以用到派他思想

  1. 排除其他 通过使用循环,将所有的元素都去除,把所有内容包括自己样式去掉
  2. 留下自己,把自己独有的样式进行设置

设置元素位置大小需要注意的问题

在设置元素大小或者是位置问题上,js代码是没问题,但是问题出在了css上,在给元素添加大小或者是移动位置,都需要给元素添加定位。

隔行变色案例,鼠标悬停

在这里巧妙的运用了一个全局变量,这个全局变量,当鼠标移入的时候,先记录一下自身的颜色,然后在进行更改,当鼠标离开的时候,将原来的颜色重新给backgroundcolor;实现鼠标鼠标移入变色

对应控制思想(tab案例)

有两组数据中储存了相同个数的元素对象,一组对象发生变化,另一组也会发生变化

实现方法

  1. 找两个数据中的共同点,两个数组中元素的下标是一样的
  2. 在对应控制思想中也会有排他思想
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;padding: 0;font-size: 15px;}

    .container { width: 500px; height: 200px;background-color: pink;}

    .tab {
      width: 100%;display: flex;align-items: center;color: white;background-color: black; border-bottom: 1px solid black;
    }

    span {flex: 1;text-align: center; padding: 10px 0px; border: 1px solid pink;margin-left: -1px;cursor: pointer;
    }

    .tab .active {background-color: pink; color: black;transition: .5s;
    }


    .item .active {display: block;color: black;
    }

    .item>div {
      display: none;
    }
  </style>
</head>

<body>
  <div class="container">
    <div class="tab" id="tab">
      <span class="active">新闻</span>
      <span>娱乐</span>
      <span>影视</span>
      <span>话题</span>
    </div>
    <div class="item" id="item">
      <div class="active">新闻</div>
      <div>娱乐</div>
      <div>影视</div>
      <div>话题</div>
    </div>
  </div>
</body>
<script>
  //获取元素
  var span = document.getElementById('tab').querySelectorAll('span');
  var item = document.getElementById('item').querySelectorAll('div');
  //鼠标悬停导航栏切换类名
  for (var i = 0; i < span.length; i++) {
    span[i].index = i;
    span[i].onmouseover = function () {
      //给span添加属性 每一个span都有下标 从0-3
      //排他思想,将选项全部排除,自己包括在内
      for (var j = 0; j < span.length; j++) {
        span[j].className = '';
        item[j].className = '';
      }
      //添加类名 
      this.className = 'active';
      //给div添加类名  span下标是多少 ,这个相同的div的下标是多少
      item[this.index].className = 'active';
    }
  }
</script>

</html>

Dom节点

创建节点 createElement

格式

新的标签(元素笔记)获取的父节点(ul)=document.createElement("标签名字")

代码案例

let item = document.createElement("div");
console.log(item);

插入节点

注意!: 在插入节点这里需要注意的是,必须先创建节点,才能将创建好的节点插入到元素内部

方式一.appendChild

格式:

父节点(通过获取节点把父节点获取到).appendChild(创建新的子节点的名字)

代码举例

<body>
    <ul>
      <li>你好</li>
      <li>我好</li>
    </ul>
  </body>
  <script>
    // 创建节点
    let li = document.createElement("li");
    let ul = document.querySelector("ul");
    // 将节点插入到ul里面
    ul.appendChild(li);
    console.log(ul);
  </script>

删除节点removeChild

格式:

父节点.removeChild(子节点)

复制节点(克隆节点)

格式如下:

    要复制的节点.cloneNode();       //括号里不带参数和带参数false,效果是一样的。

    要复制的节点.cloneNode(true);

括号里带不带参数,效果是不同的。解释如下:

  • 不带参数/带参数false:只复制节点本身,不复制子节点。

  • 带参数true:既复制节点本身,也复制其所有的子节点。

代码实例

<body>
    <ul>
      <li>你好</li>
      <li>我好</li>
    </ul>
  </body>
  <script>
    var ul = document.querySelector("ul");
    var li1 = document.createElement("li");
    ul.appendChild(li1);
    //定义变量接收复制的节点
    var li2 = li1.cloneNode();
    // 将复制的节点添加到ul里面
    ul.appendChild(li2);
    console.log(ul);
  </script>

点击a标签不跳转

<a href = "javascript:void(0);"></a>

注册事件的其他方法

addEventListener()

参数解释:

  • 参数1:事件名的字符串(注意,没有on)

  • 参数2:回调函数:当事件触发时,该函数会被执行

  • 参数3:true表示捕获阶段触发,false表示冒泡阶段触发(默认)。如果不写,则默认为false。【重要】

代码例子

<body>
    <div></div>
</body>
<script>
    var div = document.querySelector('div')
    div.addEventListener('click', function () {
        alert('hello')
    })
</script>

addEventListener使用方式

代码量较多可使用此方法

<body>
    <button>点击事件</button>
</body>
<script>
    var btn = document.querySelector('button')
    btn.addEventListener('click', mo)
    btn.addEventListener('click', mo1)
    function mo() {
        alert('htllo')
    }
     function mo1() {
        alert('htllo')
    }
</script>

注意 事件监听方法 可以对一个标签绑定多个事件而前面的事件不会被覆盖掉 依然进行

/*
需要3个值
1. type : 事件类型比如说 点击事件
2. listener :事件处理函数
3. useCapture :可选参数默认false
同一个元素可以添加多个事件
*/
btn.addEventListener("click", () => {});

移除事件

<div>1</div>
  • 1 传统方式解除绑定事件
var div = document.querySelector("div");
div.onclick = function () {
  alert("你好");
  //解除事件
  div.onclick = null;
};

attachEvent()

注册事件兼容写法(自定义)

var btn = document.getElementById("btn");
    // 调用函数
    addEvent(btn, "click",fn);
    //为了更好的解绑事件函数单独拿出来
     function fn() {
      alert(1);
    }
    // DOM 2 级事件绑定方式
    // 自己制作一个兼容所有浏览器的绑定事件的函数
    // 参数:事件源,事件类型,事件函数
    function addEvent(ele, type, fn) {
      // IE 9 及以上的浏览器和其他浏览器,使用 addEventListener 方法
      // IE 9 以下的浏览器,使用 attachEvent 方法
      // 浏览器能力检测
      if (ele.addEventListener) {
        ele.addEventListener(type, fn);
      } else if (ele.attachEvent) {
        ele.attachEvent("on" + type, fn);
      }
    }
  • 删除监听事件
var div = document.querySelector("div");
div.addEventListener("click", fn); //fn不需要调用
//可以把事件处理程序 提出来放在外面
function fn() {
  alert("你好");
  //移除监听事件
  div.removeEventListener("click", fn);
}

移除事件兼容写法(自定义)

// 移除事件
    removeEvent(btn,"click",fun);
    function fun() {
      alert(1);
    }

    // 兼容所有浏览器的 解除绑定事件的函数
    // 参数:事件源,事件类型,事件函数
    function removeEvent(ele,type,fn) {
      // 浏览器能力检测
      if (ele.removeEventListener) {
        ele.removeEventListener(type,fn);
      } else if (ele.detachEvent) {
        ele.detachEvent("on" + type,fn);
      }
    }

Dom事件流

addEventListener有三个值,第三个值是用来决定事件流

  • 参数值是布尔值,false是标识冒泡 ,true是捕获的过程

先进行捕获后进行冒泡

什么情况下会出现冒泡捕获

祖先级与目标元素同时绑定了相同的事件,再过点击目标元素的过程中,两种执行指向事件的方向

  1. 从文档Document开始向下一层一层的向下捕获
  2. 从目标元素开始向上div开始,一直到文档Document结束,是冒泡

事件流的三个阶段

• 第一个阶段:事件捕获

• 第二个阶段:事件执行过程

• 第三个阶段:事件冒泡

分别表示摸一个元素,元素绑定的事件执行的处于哪一个阶段

• onclick 类型:只能进行事件冒泡过程,没有捕获阶段

 box1.onclick = function () {
        console.log(1);
   };
  box2.onclick = function () {
            console.log(2);
    };
  box3.onclick = function () {
            console.log(3);
  };
       

控制台输出

3
2
1

• attachEvent() 方法:只能进行事件冒泡过程,没有捕获阶段

事件委托

利用事件冒泡,将子级的事件委托给父级加载 于此同时,需要利用事件函数的一个 e 参数,内部存储的是事件对象

什么时候用到事件委托?

案例:点击变色

  <ul id="list">
        <li>朴彩英</li>
        <li>郑秀妍</li>
        <li>金智妮</li>
        <li>金智秀</li>
        <li>lisa</li>
    </ul>
<script>
        // 让每个 li 被点击后,自己添加特殊的背景色,而其他兄弟不添加
        // 以前的思路:获取所有的 li 标签元素,批量添加事件
        // 事件委托:可以将一些子级的公共类型的事件委托给他们的父级添加,在父级内部想办法找到真正触发事件的最底层的事件源
        // 获取元素
        var list = document.getElementById("list");
        var lis = list.children;
        // 给 ul 添加点击事件
        list.onclick = function (e) {
            // 在内部要想办法找到真正触发事件的 li
            // 借用事件函数内部的一个参数 e,e 是事件对象
            // 只要触发事件,函数内部都可以得到一个事件对象,对象中存储了关于事件的一系列数据
            // e.target 属性记录的就是真正触发事件的事件源
            // 排除其他
            for (var i = 0 ; i < lis.length ; i++) {
                lis[i].style.backgroundColor = "";
            }
            e.target.style.backgroundColor = "pink";
        };
    </script>

思路:事件委托

事件对象

  • 只要触发事件,就会有一个对象,内部存储了与事件相关的数据

  • **e 在低版本浏览器中有兼容问题,低版本浏览器使用的是 window.event **

处理e在低版本浏览器的兼容问题

function fn(e){
    e = e || window.event;
}

解释:

当e对象在高版本浏览器里面,对e进行判断,浏览器要是可以识别,就会返回true,如果低版本在使用e对象对象的时候,识别不出来e对象,那么返回的是false,然后e对象的值就是window.event

事件对象常用属性

e.target获取真正触发事件对象

兼容写法

var target = e.target || e.srcElement;
e.clientX/e.clientY

event调用:

  • clientX:鼠标距离可视区域左侧距离。
  • clientY:鼠标距离可视区域上侧距离。

**所有浏览器都支持,鼠标距离浏览器窗口左上角的距离 **

e.pageX/e.pageY

IE8 以前不支持,鼠标距离整个HTML页面左上顶点的距离

案例:鼠标移动,图片跟随鼠标移动


思路:

  1. 给整个文档添加鼠标移动事件
  2. 获取鼠标在整个文档里的坐标clientX与clirentY
  3. 将获得的位置设置给图片,

!! 在设置图片的css注意,一定是绝对定位或者是固定定位,因为这样图片在移动过程中,不会影响到其他元素,将获取到的坐标分别给图片的left值与top值,在赋值是需要注意,要加上单位

阻止事件冒泡

大部分情况下,冒泡都是有益的。当然,如果你想阻止冒泡,也是可以的。可以按下面的方法阻止冒泡。

阻止冒泡的方法

w3c的方法:(火狐、谷歌、IE11)

    event.stopPropagation();

IE10以下则是:

event.cancelBubble = true

兼容代码如下:

   box3.onclick = function (event) {

        alert("child");

        //阻止冒泡
        event = event || window.event;

        if (event && event.stopPropagation) {
            event.stopPropagation();
        } else {
            event.cancelBubble = true;
        }
    }

上方代码中,我们对box3进行了阻止冒泡,产生的效果是:事件不会继续传递到 father、grandfather、body了。

不是所有的事件都能冒泡

以下事件不冒泡:blur、focus、load、unload、onmouseenter、onmouseleave。意思是,事件不会往父元素那里传递。

DOM特效

JS动画的主要内容如下:

1、三大家族和一个事件对象:

  • 三大家族:offset/scroll/client。也叫三大系列。

  • 事件对象/event(事件被触动时,鼠标和键盘的状态)(通过属性控制)。

2、动画(闪现/匀速/缓动)

3、冒泡/兼容/封装

偏移量属性 offset系列

js中有一套方便的获取元素尺寸的办法就是offset家族。offset家族包括:

  • offsetWidth
  • offsetHight
  • offsetLeft
  • offsetTop
  • offsetParent

1、offsetWidth 和 offsetHight

offsetWidthoffsetHight:获取元素的宽高 + padding + border,不包括margin。如下:

  • offsetWidth = width + padding + border

  • offsetHeight = Height + padding + border

这两个属性,他们绑定在了所有的节点元素上。获取元素之后,只要调用这两个属性,我们就能够获取元素节点的宽和高。

2、offsetParent

offsetParent:获取当前元素的定位父元素

  • 如果当前元素的父元素,有CSS定位(position为absolute、relative、fixed),那么 offsetParent 获取的是最近的那个父元素。

  • 如果当前元素的父元素,没有CSS定位(position为absolute、relative、fixed),那么offsetParent 获取的是body

3、offsetLeft 和 offsetTop

offsetLeft:当前元素相对于其定位父元素的水平偏移量。

offsetTop:当前元素相对于其定位父元素的垂直偏移量。

备注:从父亲的 padding 开始算起,父亲的 border 不算在内。

!!!! 注意,如果父级元素没有定位,那么获取的就是,相对于body,从左上开始,那么就

**是,如果获取的是子元素距离body的距离就是 **

**父级margin+父级border+子元素的magrin / 父级的padding **

offsetLeft 和 style.left 区别

(1)最大区别在于:

offsetLeft 可以返回无定位父元素的偏移量。如果父元素中都没有定位,则body为准。

style.left 只能获取行内样式,如果父元素中都没有设置定位,则返回""(意思是,返回空字符串);

(2)offsetTop 返回的是数字,而 style.top 返回的是字符串,而且还带有单位:px。

比如:

div.offsetLeft = 100;
div.style.left = "100px";

(3)offsetLeft 和 offsetTop 只读,而 style.left 和 style.top 可读写(只读是获取值,可写是修改值)

总结:我们一般的做法是:用offsetLeft 和 offsetTop 获取值,用style.left 和 style.top 赋值(比较方便)。理由如下:

  • style.left:只能获取行内式,获取的值可能为空,容易出现NaN。

  • offsetLeft:获取值特别方便,而且是现成的number,方便计算。它是只读的,不能赋值。

客户端大小 client 家族的组成

只于自身的元素有关系

1、clientWidth 和 clientHeight(常用)

元素调用时:

  • clientWidth:获取元素的可见宽度(width + padding)。

  • clientHeight:获取元素的可见高度(height + padding)。

body/html 调用时:

  • clientWidth:获取网页可视区域宽度。

  • clientHeight:获取网页可视区域高度。

声明

  • clientWidthclientHeight 属性是只读的,不可修改。
  • clientWidthclientHeight 的值都是不带 px 的,返回的都是一个数字,可以直接进行计算。

!!! 注意,client获取的是不包括边框的元素大小

滚动偏移属性

  • scrollLeft:获取水平滚动条滚动的距离。

  • scrollTop:获取垂直滚动条滚动的距离。

实战经验

当某个元素满足scrollHeight - scrollTop == clientHeight时,说明垂直滚动条滚动到底了。

当某个元素满足scrollWidth - scrollLeft == clientWidth时,说明水平滚动条滚动到底了。

这个实战经验非常有用,可以用来判断用户是否已经将内容滑动到底了。比如说,有些场景下,希望用户能够看完“长长的活动规则”,才允许触发接下来的表单操作。

获取 html 文档的方法

获取title、body、head、html标签的方法如下:

  • document.title 文档标题;

  • document.head 文档的头标签

  • document.body 文档的body标签;

  • document.documentElement (这个很重要)。

document.documentElement表示文档的html标签。也就是说,基本结构当中的 html 标签而是通过document.documentElement访问的,并不是通过 document.html 去访问的。

滚动事件onscroll()

当我们用鼠标滚轮,滚动网页的时候,会触发 window.onscroll() 方法。

模态框拖拽

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<style>
  #item {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 400px;
    height: 300px;
    border: 5px solid #556874;
  }

  #item .dpan {
    width: 100%;
    height: 50px;
    background: beige;
    position: relative;
  }

  .dpan button {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translate(-50%, -50%);
  }

  .pan {
    background-color: pink;
    width: 100%;
    height: 250px;
  }
</style>

<body>
  <div id="item">
    <div class="dpan">
      <button>关闭</button>
    </div>
    <div class="pan"></div>
  </div>
</body>
<script>
  // 获取元素
  var item = document.getElementById('item');
  var dpan = item.querySelector('.dpan');
  var btn = dpan.querySelector('button');
  var pan = item.querySelector('.pan');
  //点击按钮关闭
  btn.onclick = function () {
    item.style.display = 'none'
  }
  //给dpan添加鼠标按下鼠标按下触发事件
  dpan.onmousedown = function (e) {
    //获取鼠标在dpan内部的坐标
    /**
     * 如何计算鼠标在盒子内部的距离
     * 父元素距离文档左上角的距离减去鼠标在页面的位置,就得到鼠标在盒子内部的距离
     * 鼠标在盒子内部的位置=鼠标在页面上的位置-盒子的位置
     */
    //事件对象兼容
    var e = e || window.event;
    //上边距
    var l = e.pageX - item.offsetLeft;
    //下边距
    var t = e.pageY - item.offsetTop;
    //鼠标移动事件  给dpan添加鼠标移动事件
    dpan.onmousemove = function (e) {
      // 鼠标移动过程中,可以计算 item 的 left 和 top
      var nLeft = e.pageX - l;
      var nTop = e.pageY - t;
      //获取的值赋给item   注意必须加上px的单位
      item.style.left = nLeft + 'px';
      item.style.top = nTop + 'px';
    }
  }
  //鼠标弹起来
  dpan.onmouseup = function () {
    dpan.onmousemove = null;
  };
</script>

</html>

制作思路

  1. 先获取所有的元素
  2. 给元素添加鼠标按下事件
  3. 定义两个变量接收鼠标按下是获取的坐标,存到变量里
  4. 添加鼠标移动事件
  5. 在移动的过程中获取box的位置信息
  6. 将值赋给父盒子,实现跟随鼠标移动
  7. 添加鼠标弹起事件

BOM链接

https://www.jianshu.com/p/a0eed6399684

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一、Web API介绍 1.1 API的概念 API(Application Programming Interf...
    AizawaSayo阅读 3,544评论 0 4
  • webAPI API:应用程序编程接口 是预先定义的函数,目的是提供应用程序与开发人员基于某个软件或硬件得以访问一...
    你好好想想_be60阅读 2,890评论 0 1
  • 有的没的 DOM就是把html视为一个层次结构(树形结构)的文档 文档(Document):一个页面就是一个文档,...
    哎呦呦胖子斌阅读 4,082评论 0 0
  • API的概念 API是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,无需...
    安掌门dear阅读 2,790评论 0 1
  • JS的组成 ECMAScript js的基础语法 DOM 文档对象模型 BOM ...
    北冥有鱼_425c阅读 3,811评论 0 1