节点操作

为什么要学节点操作?

这两种方式都可以获取元素节点,我们后面都会使用,但是节点操作更简单

 

获取元素通常使用两种方式:

1.利用DOM提供的方法获取元素

document.getElementByid()

document.getElementsByTagName()

document.querySelector 等

逻辑性不强,繁琐

 

2.利用节点层级关系获取元素

利用父子兄节点关系获取元素

逻辑性强,但是兼容性稍差

 

 

节点概述:

网页中的所有内容都是节点(标签、属性、文本、注释等)、在DOM中,节点使用node来表示。

HTML DOM树中的所有节点均可通过JavaScript进行访问、所有HTML元素(节点)均可被修改,也可以创建或删除

一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性

  • 元素节点 nodeType为1
  • 属性节点 nodeType为2
  • 文本节点 nodeType为3(文本节点包含文字、空格、换行等)

我们在实际开发中、节点操作主要操作的是元素节点

 

 

节点层级

利用DOM树可以把节点划分为不同的层级关系,常见的是父子兄层级关系

 

1.父级节点

node.parentNode

parentNode属性可返回某节点的父节点、注意是最近一个父节点

如果指定的节点没有父节点则返回null

 

 

三种动态创建元素的区别

 

doucument.write()
element.innerHTML
document.createElement()
区别:

 

document.write() 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘
innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂

<body>
    <div class="innner"></div>
    <div class="create"></div>
    <script>
        // 2. innerHTML 创建元素
        var inner = document.querySelector('.inner');
        // 2.1 innerHTML 用拼接字符串方法
        for (var i = 0; i <= 100; i++) {
            inner.innerHTML += '<a href="#">百度</a>';
        }
        // 2.2 innerHTML 用数组形式拼接
        var arr = [];
        for (var i = 0; i <= 100; i++) {
            arr.push('<a href="#">百度</a>');
        }
        inner.innerHTML = arr.join('');

        // 3.document.createElement() 创建元素
        var create = document.querySelector('.create');
        var a = document.createElement('a');
        create.appendChild(a);
    </script>
</body>
  • createElement()创建多个元素效率稍低一点点,但是结构更清晰

  总结:不同浏览器下, innerHTML 效率要比 createElement 高

 

DOM核心
对于DOM操作,我们主要针对子元素的操作,主要有

创建




属性操作
时间操作
6.1、创建
document.write
innerHTML
createElement
6.2、增
appendChild
insertBefore
6.3、删
removeChild
6.4、改
主要修改dom的元素属性,dom元素的内容、属性、表单的值等
修改元素属性:src、href、title 等
修改普通元素内容:innerHTML、innerText
修改表单元素:value、type、disabled
修改元素样式:style、className
6.5、查
主要获取查询dom的元素
DOM提供的API方法:getElementById、getElementsByTagName (古老用法,不推荐)
H5提供的新方法:querySelector、querySelectorAll (提倡)
利用节点操作获取元素:父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling) 提倡
6.6、属性操作
主要针对于自定义属性
setAttribute:设置dom的属性值
getAttribute:得到dom的属性值
removeAttribute:移除属性
7、事件高级
7.1、注册事件(绑定事件)
给元素添加事件,称为注册事件或者绑定事件。

注册事件有两种方式:传统方式和方法监听注册方式

 

 

addEventListener事件监听方式

  • eventTarget.addEventListener()方法将指定的监听器注册到 eventTarget(目标对象)上
  • 当该对象触发指定的事件时,就会执行事件处理函数
    eventTarget.addEventListener(type,listener[,useCapture])

    该方法接收三个参数:

    • type:事件类型字符串,比如click,mouseover,注意这里不要带on
    • listener:事件处理函数,事件发生时,会调用该监听函数
    • useCapture:可选参数,是一个布尔值,默认是 false。学完 DOM 事件流后,我们再进一步学习
    • <body>
          <button>传统注册事件</button>
          <button>方法监听注册事件</button>
          <button>ie9 attachEvent</button>
          <script>
              var btns = document.querySelectorAll('button');
              // 1. 传统方式注册事件
              btns[0].onclick = function() {
                  alert('hi');
              }
              btns[0].onclick = function() {
                      alert('hao a u');
                  }
                  // 2. 事件监听注册事件 addEventListener 
                  // (1) 里面的事件类型是字符串 所以加引号 而且不带on
                  // (2) 同一个元素 同一个事件可以添加多个侦听器(事件处理程序)
              btns[1].addEventListener('click', function() {
                  alert(22);
              })
              btns[1].addEventListener('click', function() {
                      alert(33);
                  })
                  // 3. attachEvent ie9以前的版本支持
              btns[2].attachEvent('onclick', function() {
                  alert(11);
              })
          </script>
      </body>

      attachEvent事件监听方式(兼容)

      • eventTarget.attachEvent()方法将指定的监听器注册到 eventTarget(目标对象) 上
      • 当该对象触发指定的事件时,指定的回调函数就会被执行
        eventTarget.attachEvent(eventNameWithOn,callback)

        该方法接收两个参数:

        eventNameWithOn:事件类型字符串,比如 onclick 、onmouseover ,这里要带 on
        callback: 事件处理函数,当目标触发事件时回调函数被调用
        ie9以前的版本支持
        ③注册事件兼容性解决方案
        兼容性处理的原则:首先照顾大多数浏览器,再处理特殊浏览器

         function addEventListener(element, eventName, fn) {
              // 判断当前浏览器是否支持 addEventListener 方法
              if (element.addEventListener) {
                element.addEventListener(eventName, fn);  // 第三个参数 默认是false
              } else if (element.attachEvent) {
                element.attachEvent('on' + eventName, fn);
              } else {
                // 相当于 element.onclick = fn;
                element['on' + eventName] = fn;
         } 

        删除事件(解绑事件)

        7.2.1、removeEventListener删除事件方式

        eventTarget.removeEventListener(type,listener[,useCapture]);

        该方法接收三个参数:

        type:事件类型字符串,比如click,mouseover,注意这里不要带on
        listener:事件处理函数,事件发生时,会调用该监听函数
        useCapture:可选参数,是一个布尔值,默认是 false。学完 DOM 事件流后,我们再进一步学习
        7.2.2、detachEvent删除事件方式(兼容)

      • eventTarget.detachEvent(eventNameWithOn,callback);

         

        该方法接收两个参数:

        • eventNameWithOn:事件类型字符串,比如 onclick 、onmouseover ,这里要带 on
        • callback: 事件处理函数,当目标触发事件时回调函数被调用
        • ie9以前的版本支持

        7.2.3、传统事件删除方式

      • eventTarget.onclick = null;
        <body>
            <div>1</div>
            <div>2</div>
            <div>3</div>
            <script>
                var divs = document.querySelectorAll('div');
                divs[0].onclick = function() {
                    alert(11);
                    // 1. 传统方式删除事件
                    divs[0].onclick = null;
                }
                // 2.removeEventListener 删除事件
                divs[1].addEventListener('click',fn);   //里面的fn不需要调用加小括号
        
                function fn(){
                    alert(22);
                    divs[1].removeEventListener('click',fn);
                }
                // 3.IE9 中的删除事件方式
                divs[2].attachEvent('onclick',fn1);
                function fn1() {
                    alert(33);
                    divs[2].detachEvent('onclick',fn1);
                }
            </script>
        
        </body>

        7.2.4、删除事件兼容性解决方案

         function removeEventListener(element, eventName, fn) {
              // 判断当前浏览器是否支持 removeEventListener 方法
              if (element.removeEventListener) {
                element.removeEventListener(eventName, fn);  // 第三个参数 默认是false
              } else if (element.detachEvent) {
                element.detachEvent('on' + eventName, fn);
              } else {
                element['on' + eventName] = null;
         } 

        DOM事件流

        • 事件流描述的是从页面中接收事件的顺序
        • 事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流

           

           

          事件冒泡: IE 最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点的过程。

          事件捕获: 网景最早提出,由 DOM 最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程。

          加深理解:

          我们向水里面扔一块石头,首先它会有一个下降的过程,这个过程就可以理解为从最顶层向事件发生的最具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点( 最具体元素)之后漂浮到水面上,这个过程相当于事件冒泡。

           

           

          7.3.1、捕获阶段

          • document -> html -> body -> father -> son

          两个盒子嵌套,一个父盒子一个子盒子,我们的需求是当点击父盒子时弹出 father ,当点击子盒子时弹出 son

          <body>
              <div class="father">
                  <div class="son">son盒子</div>
              </div>
              <script>
                  // dom 事件流 三个阶段
                  // 1. JS 代码中只能执行捕获或者冒泡其中的一个阶段。
                  // 2. onclick 和 attachEvent(ie) 只能得到冒泡阶段。
                  // 3. 捕获阶段 如果addEventListener 第三个参数是 true 那么则处于捕获阶段  document -> html -> body -> father -> son
                  var son = document.querySelector('.son');
                  son.addEventListener('click', function() {
                       alert('son');
                  }, true);
                  var father = document.querySelector('.father');
                  father.addEventListener('click', function() {
                      alert('father');
                  }, true);
              </script>
          </body>

          这是因为捕获阶段由 DOM 最顶层节点开始,然后逐级向下传播到到最具体的元素接收

          document -> html -> body -> father -> son

          先看 document 的事件,没有;再看 html 的事件,没有;再看 body 的事件,没有;再看 father 的事件,有就先执行;再看 son 的事件,再执行。

          7.3.2、冒泡阶段
          son -> father ->body -> html -> document

          <body>
              <div class="father">
                  <div class="son">son盒子</div>
              </div>
              <script>
                  // 4. 冒泡阶段 如果addEventListener 第三个参数是 false 或者 省略 那么则处于冒泡阶段  son -> father ->body -> html -> document
                  var son = document.querySelector('.son');
                  son.addEventListener('click', function() {
                      alert('son');
                  }, false);
                  var father = document.querySelector('.father');
                  father.addEventListener('click', function() {
                      alert('father');
                  }, false);
                  document.addEventListener('click', function() {
                      alert('document');
                  })
              </script>
          </body>

          7.3.3、小结
          JS 代码中只能执行捕获或者冒泡其中的一个阶段

          onclick 和 attachEvent只能得到冒泡阶段

          addEventListener(type,listener[,useCapture])第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false (不写默认就是false),表示在事件冒泡阶段调用事件处理程序

          实际开发中我们很少使用事件捕获,我们更关注事件冒泡。

          有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave

          7.4、事件对象

          eventTarget.onclick = function(event) {
             // 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt 
          } 
          eventTarget.addEventListener('click', function(event) {
             // 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt  
          })

           

posted @ 2022-04-18 09:31  奥摩前端  阅读(140)  评论(0编辑  收藏  举报