事件冒泡与事件捕获

事件冒泡和捕获分别是是由微软和网景公司提出的,这两个概念都是为了解决页面中事件流(事件发生顺序)的问题。

    <div>
        <p>点击</p>
    </div>

  事件冒泡: 子级元素先触发,父级元素后触发,即p先触发,div后触发。发生事件的顺序为 p -> div -> body -> html -> document。
  事件捕获: 父级元素先触发,子级元素后触发,即div先触发,p后触发。发生事件的顺序为 document -> html -> body -> div -> p。

在DOM0级事件中(ele.onclick=function(){} ),在IE、Firefox、Chrome、opera下事件执行顺序都是事件冒泡。
在DOM2级事件中(ele.addEventListener(event, fn, boolean)),当第3个参数为true时表示事件捕获,为false时表示事件冒泡,默认为false。

事件委托

  事件委托: 利用事件冒泡的原理,将多个子元素上的(一类型)事件,放在父元素上,在父元素上创建一个事件处理程序来管理这一类型的所有事件。
  事件委托的优点:
    1) 由于每一个函数都是对象,对象会占用内存,内存的占用关系到性能,而使用事件委托后,会减少事件处理程序。因此,减少了内存占用,性能更好。
    2) 如果要为许多DOM元素绑定事件,需要多长访问DOM,设置事件处理程序所需时间更长,整个页面就绪需要的时间越多。事件委托技术可以避免对每个字元素添加事件监听器,减少操作DOM节点的次数,从而减少浏览器的重绘和重排,提高代码的性能。

例:

     <ul>
        <li data-id="1">1</li>
        <li data-id="2">2</li>
        <li data-id="3">3</li>
    </ul>
    
    <script>
        let ulEle = document.querySelector('ul');
        ulEle.onclick = function (event) {
            let val = event.target.dataset.id;
            if (typeof val !== 'undefined') {
                alert(val);
            }
        }
    </script>

扩展

DOM0级事件绑定和DOM2级事件绑定

DOM0级事件绑定
  DOM0级事件绑定的原理
  1.给当前元素的某一私有属性(onXXX)赋值的过程;(之前属性默认值是null,如果我们赋值了一个函数,就相当于绑定了一个方法)
                2.当我们赋值成功(赋值一个函数),此时浏览器会把DOM元素和赋值的的函数建立关联,以及建立DOM元素的行为监听,当某一行为被用户触发,浏览器会把赋值的函数执行

  DOM0级事件绑定的特点:
    1.在DOM0级事件绑定中,只能给当前元素的某一个行为绑定一个方法,绑定多个方法时,最后一次绑定的事件会替换前面绑定的。
    2.移除事件绑定时只需要赋值为null。
  例:

    // 绑定事件
    btn.onclick = function() {
        console.log('123');
        // 移除事件
        btn.onclick = null;
    }

DOM2级事件绑定:
  DOM2级事件绑定的原理
    1.DOM2级事件绑定使用的 addEventListener/attachEvent方法都是在eventTarget这个内置类的原型上定义的,调用的时候,首先要通过原型链找到这个方法,然后执行完成事件的绑定效果。
    2.浏览器会给当前元素的行为开辟一个事件池(事件队列)[浏览器有一个统一的事件池,每个元素绑定的行为都在这里,通过相关标准区分],通过 addEventListener/attachEvent进行事件绑定时,会把绑定的方法放在事件池中。
    3.当元素的某一行为被触发,浏览器回到对应事件池中,把当前放在事件池的所有方法按序依次执行

  DOM2级事件绑定的特点
    1.所有DOM0支持的行为,DOM2都可以用,DOM2还支持DOM0没有的事件行为(这样说比较笼统)【浏览器会把一些常用事件挂载到元素对象的私有属性上,让我们可以实现DOM0事件绑定,DOM2:凡是浏览器给元素天生设置的事件在DOM2中都可以使用】
    2.DOM2中可以给当前元素的某一事件行为绑定多个不同方法(因为绑定的所有方法都放在事件池中)
    3.事件的移除:事件类型、绑定的方法、传播阶段三个完全一致,才可以完成移除(因此在绑定方法时,尽量不要用匿名函数,否则不好移除)
注:在DOM第一代升级迭代的时候,事件绑定依然沿用DOM0级绑定的方式。
  例:

    // 添加事件
    divEle.addEventListener('click', say);
    function say() {
        console.log(123);
        // 移除事件
        divEle.removeEventListener('click', say);
    }

参考文章:
  JS基础知识(十一)DOM0和DOM2级事件:
https://blog.csdn.net/qq_2338...
  浅谈事件冒泡与事件捕获: https://segmentfault.com/a/11...


雨夜望月
207 声望13 粉丝