JavaScript | DOM事件流

125 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

前言

JavaScript是基础并且是非常重要的一部分,现在项目基本都靠框架开发,很多原生方法得不到使用就会慢慢忘记,所以借着6月更文好好复习一下基础知识,今天讲讲DOM事件流。

文档碎片节点

当我们去大量去操作DOM的时候,势必会引起性能问题,因为页面会进行重新渲染,造成重绘重排,而重绘重排是DOM编程中耗能的主要原因之一,而我们需要利用文档碎片节点的方式来减少页面的重绘重排。

关于重排(回流)与重绘的基本介绍

重排(回流)

  • 当render tree中的一部分或者是全部,因为元素的尺寸、布局、隐藏等等改变引起页面的重新渲染,这个过程称作为重排

重绘

  • 当render tree(渲染树)中更新的属性只会影响元素的外观、风格,不会影响元素的布局的时候,浏览器需要重新绘制当前元素的样式,被称作为重绘。 重绘不会引起重排,但重排一定会引起重绘,一个元素的重排通常会带来一系列的反应,甚至触发整个文档 的重排和重绘,性能代价是高昂的

关于文档碎片节点的具体使用

   <body>
      <ul class="box"></ul>
   </body>
   
   <script>
         var oBox = document.querySelector('.box')
         oBox.onclick = function(){
         //首先创建文档碎片节点
           var oFrag = document.createDocumentFragment();
           //比如说要插入很多元素
           for(var i = 0; i < 100; i++){
            var newLi = document = createElement('li');
            newLi.innerHtml = 'text';
            //保存在文档碎片节点里
            oFrag.appendChild(newLi)
           }
           //一次性加入,只渲染一次页面
           oBox.appendChild(oFrag)
         }
   </script>

事件流(事件模型、事件机制)

多个节点对象对同一个事件的响应顺序,被称作为事件流

谈谈w3c事件流

  • 执行捕获阶段:网景浏览器提出,事件由最不精确的对象(document)依次执行到最精确的目标元素(target)
  • 执行冒泡阶段:IE浏览器提出,事件由最精确的目标元素(target) 依次执行到 最不精确的对象(document)
  • 事件根据自身是冒泡还是捕获,决定自身在哪一个阶段执行

事件处理函数

  • w3c提供了一个事件处理函数 addEventListener()也就是DOM2级事件处理函数 专门用来处理事件
    • 参数1:事件名称 (没有on)
    • 参数2:事件函数
    • 参数3:布尔值,代表冒泡(false)或捕获(true)时候触发,默认false
  • 特点
    • 可以给同一个元素绑定同一个事件多次
    • 可以控制冒泡和捕获
  • 删除事件:使用removeEventListener()方法
    • 参数1:移除的事件名
    • 参数2:移除当前事件名的哪一个事件函数
    • 参数3:移除的当前事件是冒泡阶段还是捕获阶段 是一个布尔值
  • 使用场景
    • 对同一个元素绑定同一个事件多次 不希望被覆盖
    • 可以控制捕获或者冒泡
    • DOM2级事件 只能通过事件处理函数绑定(DOMContentLoaded)

    通过一个小demo来熟悉一下DOM2级事件处理函数

动画.gif

<body>
<button class="btn">取消点击</button>
<div class="text">点我弹出信息</div>
</body>

<script>
       var oBtn = document.querySelector('.btn')
       var oText = document.querySelector('.text')
       
       //弹出信息事件函数
       function fn(){
          alert('我弹出来了')
       }
       //点击弹出信息
       oText.addEventListener('click',fn,false)
       
       //取消点击事件
       oBtn.onclick = function(){
          oText.removeEventListener('click',fn,false)
       }
</script>

事件对象

event

  • 当事件发生的时候,有一个对象保存的是当前事件所有相关的信息,这个对象被称作为event事件对象
  • 获取:function(event){} || window.event 阻止默认事件
  • event.preventDefault()
  • 阻止传播:即冒泡或捕获 event.stopPropagation

事件委托

事件委托属于一个小优化点,其实就是利用冒泡原理把子元素需要触发的绑定在父元素上,通过event事件对象的target属性,获取当前点击的精确元素,减少了绑定次数,提交效率,而且未来在父元素下面的子元素也不需要重新绑定,可以直接操作。

通过一个demo演示一下事件委托

动画.gif

  <body>
    <button class="btn">添加</button>
    <ul class="box">
        <li>1</li>
        <li>2</li>
    </ul>
</body>

<script>
      var oBtn = document.querySelector('.btn')
      var oBox = document.querySelector('.box')

       //使用事件委托到父元素上,通过event.target来找到对应的子元素,还可以给未来添加的li添加颜色
      oBox.onclick = function (event){
            if(event.target.nodeName.toLowerCase()==='li'){
                event.target.style.background = 'pink'
            }
      }
      
      oBtn.onclick = function(){
         var newLi = document.createElement('li')
         newLi.textContent = '新添加的li'
         oBox.appendChild(newLi)
      }
</script>

好了,以上就是本篇文章的分享,感谢阅读!