Day3 DOM-节点操作

3.1 节点
  • 节点:标签、文本、注释、换行等,节点类型nodeType、节点名称nodeName、节点值nodeValue

    元素:标签

  • 节点层级:父节点、子节点、兄弟节点

    parentNode父节点的最大节点是document,再朝上查找就是null

    prentElement最大父元素是html,再朝上查找就是null

    <!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>
      <div>father
        <span>son</span>
      </div>
      <script>
        let span=document.querySelector('span')
        console.log(span.parentNode)  //div下的东西
        console.log(span.parentNode.parentNode.parentNode.parentNode)  //null
        let li=document.querySelector('li')
        console.log(li)  //null
        console.log(span.parentElement)  //div下的东西
        console.log(span.parentElement.parentElement.parentElement.parentElement)  //null
      </script>
    </body>
    </html>
  • 子节点---childNodes;子元素---children拿到伪数组,开发中常用

    firstChild---第一个子节点;firstElementChild---第一个子元素(ie9以上才支持)

    lastChild---最后一个子节点;lastElementChild---最后一个子元素(ie9以上才支持)

    nodeType的换行---3、注释---8、元素---1

  • 兄弟节点

    nextSibling---下一个兄弟节点;previousSibling---上一个兄弟节点

    nextElementChild---下一个兄弟元素;previousElementSibling---上一个兄弟元素

    <!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>
      <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
      </ul>
      <script>
        let ul=document.querySelector('ul')
        let li_second=ul.children[1]  //ul的第二个子元素
        console.log(li_second.nextSibling)  //ul的第二个子元素的下一个兄弟节点
        console.log(li_second.nextElementSibling)  //ul的第二个子元素的下一个兄弟元素
        let li_fourth=ul.children[3]  //ul的第四个子元素
        console.log(li_fourth.previousSibling)  //ul的第4个子元素的上一个兄弟节点
        console.log(li_fourth.previousElementSibling)  //ul的第4个子元素的上一个兄弟元素
      </script>
    </body>
    ​
    </html>
  • 添加节点

    1. 创建元素节点---createElement('标签名')

    2. 添加元素节点---parentNode.appendChild(变量名)

    3. 添加新增元素的内容---变量名.innerText=' '

    给兄弟元素前面插入兄弟元素---insertBefore(加谁,加在谁前面)

  • 删除元素---removeChild(元素)

    remove():括号内不写元素,则删除了所有

  • 替换节点---replaceChild(新节点,旧节点)

  • 克隆节点---cloneNode() 只克隆自己的标签,里面的内容未被克隆

    cloneNode(true) 克隆自己以及自己的子孙后代和内容​

练习

<body>
  <ul></ul>
  <button>新增</button>
  <script>
    let arr = ['赵龙', '卢兴愿', '吴鑫', '龚政', '钱民君']
    let ul = document.querySelector('ul')
    let btn_append=document.querySelector('button')
    // 将数组中元素添加到ul中
    for (let i = 0; i < arr.length; i++) {
      let li = document.createElement('li')
      ul.appendChild(li)
      li.innerText = arr[i]
      // 添加删除按钮
      let btn = document.createElement('button')
      li.appendChild(btn)
      btn.innerText = '删除'
      // 添加删除事件
      /*btn.onclick = function () {
        btn.parentNode.remove()
      }*/
​
      btn.onclick =remove
      function remove(){
        this.parentNode.remove()
      }
    }
​
    btn_append.onclick=function(){
      let newValue=prompt('请输入新数据:')
      let li = document.createElement('li')
      ul.appendChild(li)
      li.innerText = newValue
      // 添加删除按钮
      let btn = document.createElement('button')
      li.appendChild(btn)
      btn.innerText = '删除'
      // 添加删除事件
      btn.onclick = function () {
        btn.parentNode.remove()
      }
    }
​
  </script>
​
</body>
​
<body>
<button>按钮</button>
  <script>
    var btn=document.querySelector('button')
    for(var i=0;i<10;i++){
      // 鼠标点击后,for循环已经完成了,所以此时的i=10
      btn.onclick=function(){
        console.log(i)  //10
      }
    }
  </script>
</body>

案例

<!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>
  <!-- <ul></ul>
  <button>添加</button>
  <script>
    let ul = document.querySelector('ul')
    let btn = document.querySelector('button')
    let arr = ['曹鑫宇', '康硕涵', '龚政', '赵龙', '吴穹', '任杰', '钱民君', '盛庆奥', '张国庆', '蔡浩男', '章杰', '卢兴愿', '吴鑫']
    // 按钮添加点击事件
    btn.onclick = fn1
    function fn1() {
      if (arr.length == 0) {
        alert('添加完毕')
        btn.onclick = null
      } else {
        let li = document.createElement('li')
        ul.appendChild(li)
        li.innerText = arr[0]
        arr.shift()
      }
      // li变红
      let lis = document.querySelectorAll('li')
      for (let i = 0; i < lis.length; i++) {
        // li背景颜色点击事件
        lis[i].onclick = fn2
      }
    }
    function fn2() {
      let lis = document.querySelectorAll('li')
      for (let j = 0; j < lis.length; j++) {
        lis[j].style.backgroundColor = ''
      }
      this.style.backgroundColor = 'red'
    }
  </script> -->
​
  <!-- 方式2: -->
  <!-- <ul></ul>
  <button>添加</button>
  <script>
    let ul = document.querySelector('ul')
    let btn = document.querySelector('button')
    let arr = ['曹鑫宇', '康硕涵', '龚政', '赵龙', '吴穹', '任杰', '钱民君', '盛庆奥', '张国庆', '蔡浩男', '章杰', '卢兴愿', '吴鑫']
    let num = 0
    btn.onclick = function () {
      if (num == arr.length) {
        alert('添加完毕')
        btn.onclick = null
      } else {
        let li = document.createElement('li')
        ul.appendChild(li)
        li.innerText = arr[num]
        num++
      }
​
      for (let j = 0; j < ul.children.length; j++) {
        ul.children[j].onclick = fun
      }
    }
    function fun() {
      for (let k = 0; k < ul.children.length; k++) {
        ul.children[k].style.backgroundColor = ''
      }
      this.style.backgroundColor = 'red'
    }
  </script> -->
​
  <!-- 方式3: -->
  <ul></ul>
  <button>添加</button>
  <script>
    var arr = ['曹鑫宇', '康硕涵', '龚政', '赵龙', '吴穹', '任杰', '钱民君', '盛庆奥', '张国庆', '蔡浩男', '章杰', '卢兴愿', '吴鑫']
    let ul = document.querySelector('ul')
    let but = document.querySelector('button')
    let num = 0
    but.onclick = function () {
      if (num == arr.length) {
        alert('数据已经添加完了')
        but.onclick = null
      } else {
        let lili = document.createElement('li')
        ul.appendChild(lili)
        lili.innerText = arr[num]
        num++
      }
    }
    // 事件委托--- li委托给了父元素 ul
    ul.onclick = function (e) {
      for (let j = 0; j < ul.children.length; j++) {
        ul.children[j].style.backgroundColor = ''
      }
      // e.target指向触发的事件对象
      if (e.target.tagName == 'LI') {
        e.target.style.backgroundColor = 'red'
      }
    }
  </script>
​
​
</body>
​
</html>

3.2 DOM事件流

DOM事件流分三个阶段:捕获 目标元素 冒泡

捕获阶段:document -> html -> body ->父元素 ->目标元素

冒泡阶段: 目标元素->父元素->body -> html -> document

onclick只能拿到冒泡阶段,不能拿到捕获阶段

<!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>
    .f{
      width: 400px;
      height: 400px;
      background-color: pink;
    }
    .s{
      width: 100px;
      height: 100px;
      background-color: skyblue;
    }
  </style>
</head>
​
<body>
  <div class="f">father
    <div class="s">son</div>
  </div>
  <script>
    let f=document.querySelector('.f')
    let s=document.querySelector('.s')
    f.onclick=function(){
      alert('father')
    }
    // 触发s事件时,先弹出son再弹出father
    s.onclick=function(){
      alert('son')
    }
  </script>
</body>
​
</html>
  • 注册事件方法

    • 传统事件:给元素重复注册一个事件时,只会执行最后一个(冒泡阶段)---onclick 、oninput 、onmousemove

      传统事件的删除方法---元素.事件类型=null

    • 事件监听(ie9以上):给元素重复注册一个事件时,都会执行(第三个布尔值为true为捕获阶段,false或者空则为冒泡阶段)--- 元素.addEventListerner('事件类型',function(){ })

      监听事件的删除方法---元素.removeEventListerner('事件类型',function(){ })

  • 事件流的特点

    传统事件只有冒泡阶段,没有捕获阶段

    事件监听:元素.addEventListerner('事件类型',事件处理函数,布尔值)

    布尔值省略或者为false,会触发冒泡阶段;布尔值为true时,会触发捕获阶段

3.3 事件对象
  • 事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象。

    比如:

    1.事件对象的使用

    事件触发发生时就会产生事件对象,并且系统会以实参的形式传给事件处理函数

    所以,在事件处理函数中声明1个形参用来接收事件对象。

    2.事件对象的兼容性处理

    事件对象本身的获取存在兼容问题:

     <div>123</div>
        <script>
            var div = document.querySelector('div');
            div.onclick = function(e) {
                    // 事件对象
                    e = e || window.event;
                    console.log(e);
            }
        </script>

    3.e.target 和 this 的区别

    常情况下terget 和 this是一致的,
    但有一种情况不同,那就是在事件冒泡时(父子元素有相同事件,单击子元素,父元素的事件处理函数也会被触发执行)
    这时候this指向的是父元素,因为它是绑定事件的元素对象,
    而target指向的是子元素,因为他是触发事件的那个具体元素对象。 
    <div>123</div>
        <script>
            var div = document.querySelector('div');
            div.addEventListener('click', function(e) {
                // e.target 和 this指向的都是div
                console.log(e.target);
                console.log(this);
    ​
            });
        </script>

    事件冒泡下的e.target和this

    <ul>
            <li>abc</li>
            <li>abc</li>
            <li>abc</li>
        </ul>
        <script>
            var ul = document.querySelector('ul');
            ul.addEventListener('click', function(e) {
                  // 我们给ul 绑定了事件  那么this 就指向ul  
                  console.log(this); // ul
    ​
                  // e.target 触发了事件的对象 我们点击的是li e.target 指向的就是li
                  console.log(e.target); // li
            });
        </script>

    阻止默认行为

    html中一些标签有默认行为,例如a标签被单击后,默认会进行页面跳转。

    e.preventDefault()----dom标准写法

    return false;-----没有兼容性问题

    e.returnValue = false;------有兼容性问题

     <a href="http://www.baidu.com">百度</a>
        <script>
            // 2. 阻止默认行为 让链接不跳转 
            var a = document.querySelector('a');
            a.addEventListener('click', function(e) {
                 e.preventDefault(); //  dom 标准写法
            });
            // 3. 传统的注册方式
            a.onclick = function(e) {
                // 普通浏览器 e.preventDefault();  方法
                e.preventDefault();
                // 低版本浏览器 ie678  returnValue  属性
                e.returnValue = false;
                // 我们可以利用return false 也能阻止默认行为 没有兼容性问题
                return false;
            }
        </script>

    阻止事件冒泡

    事件冒泡本身的特性,会带来的坏处,也会带来的好处。

    e.stopPropagation(); ----阻止冒泡

    window.event.cancelBubble = true;------了解

       
     <div class="father">
            <div class="son">son儿子</div>
        </div>
        <script>
            var son = document.querySelector('.son');
            // 给son注册单击事件
            son.addEventListener('click', function(e) {
                alert('son');
                e.stopPropagation(); // stop 停止  Propagation 传播
                window.event.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡
            }, false);
    ​
            var father = document.querySelector('.father');
            // 给father注册单击事件
            father.addEventListener('click', function() {
                alert('father');
            }, false);
            // 给document注册单击事件
            document.addEventListener('click', function() {
                alert('document');
            })
        </script>
    1. 谁绑定了这个事件。

    2. 鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置。

    3. 键盘触发事件的话,会得到键盘的相关信息,如按了哪个键。

    4. 标准浏览器中是浏览器给方法传递的参数,只需要定义形参 e 就可以获取到。

    5. 在 IE6~8 中,浏览器不会给方法传递参数,如果需要的话,需要到 window.event 中获取查找。

    • this 是事件绑定的元素(绑定这个事件处理函数的元素) 。

    • e.target 是事件触发的元素。

  • 事件委托

    什么是事件委托

    把事情委托给别人,代为处理。

    不给子元素注册事件,给父元素注册事件,把处理代码在父元素的事件中执行。

    事件委托的原理

    给父元素注册事件,利用事件冒泡,当子元素的事件触发,会冒泡到父元素,然后去控制相应的子元素。

    事件委托的作用

    • 我们只操作了一次 DOM ,提高了程序的性能。

    • 动态新创建的子元素,也拥有事件。

        
       <ul>
              <li>今天是快乐的一天!</li>
              <li>今天是快乐的一天!</li>
              <li>今天是快乐的一天!</li>
              <li>今天是快乐的一天!</li>
              <li>今天是快乐的一天!</li>
          </ul>
          <script>
              // 事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点
              var ul = document.querySelector('ul');
              ul.addEventListener('click', function(e) {
                  // e.target 这个可以得到我们点击的对象
                  e.target.style.backgroundColor = 'pink';
              })
          </script>

  • 获取鼠标在页面的坐标

    屏幕可视区域:e.clientX、e.clientY

    页面:e.pageX、e.pageY----会随着页面滑动坐标发生变化

    浏览器距离电脑屏幕:e.screenX、e.screenY

       
     <script>
            // 鼠标事件对象 MouseEvent
            document.addEventListener('click', function(e) {
                // 1. client 鼠标在可视区的x和y坐标
                console.log(e.clientX);
                console.log(e.clientY);
         
    ​
                // 2. page 鼠标在页面文档的x和y坐标
                console.log(e.pageX);
                console.log(e.pageY);
          
    ​
                // 3. screen 鼠标在电脑屏幕的x和y坐标
                console.log(e.screenX);
                console.log(e.screenY);
    ​
            })
        </script>

案例

<!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>
    body {
      background-color: blueviolet;
    }
​
    .div {
      width: 100px;
      height: 100px;
      background-color: skyblue;
      position: absolute;
      top: 0;
      left: 0;
    }
​
    img {
      width: 100%;
      height: 100%;
    }
​
    .box {
      width: 300px;
      height: 300px;
      background-color: pink;
      margin-top: 300px;
      margin-left: 500px;
    }
  </style>
</head>
​
<body>
  <div class="div">
    <img src="../images/fresh_goods_7.jpg" alt="">
  </div>
  <div class="box"></div>
  <script>
    // 鼠标按下(在图片区域按下)拖拽盒子才会移动 
    // 鼠标在中间盒子区域外松开后盒子停止移动
    // 鼠标在中间盒子区域松开 图片会展示在中间盒子内,然后图片回到原始位置
​
    // 有个盒子,获取元素,给元素添加事件
    var div = document.querySelector('.div')
    var img = document.querySelector('img')
    var box = document.querySelector('.box')
    div.onmousedown = function (e) {
      // 把鼠标点击的坐标赋给div的top和left
      div.style.top = e.clientY + 'px'
      div.style.left = e.clientX + 'px'
      // 鼠标先在图片上按下后才能进行移动事件
      document.onmousemove = function (e) {
        div.style.top = e.clientY + 'px'
        div.style.left = e.clientX + 'px'
      }
    }
    // 添加鼠标抬起事件,让图片停止移动
    div.onmouseup = function (e) {
      // 清除鼠标在文档中的移动事件
      document.onmousemove = null
      // 通过div的第一个孩子img来获取图片的路径
      var imgSrc = this.children[0].src
      // 鼠标在y轴方向坐标300-500,图片才能完全在box里
      // 鼠标在x轴方向坐标500-700,图片才能完全在box里
      if (e.clientX > 500 && e.clientX < 800 && e.clientY > 300 && e.clientY < 600) {
        // 原本box里面没有img,所以box_img初始状态为null
        var box_img = box.querySelector('img')
        div.style.top = 0
        div.style.left = 0
        // 当box第一次获取到图片后,box_img=true
        if (box_img) return
        // 创建img
        var img = document.createElement('img')
        img.src = imgSrc
        box.appendChild(img)
      }
    }
​
​
​
  </script>
</body>
​
</html>

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值