[Js茶话会]-事件冒泡机制和事件委托

1,927 阅读3分钟

冒泡机制

先看图: 9bdb130e10ccd8b79c05b9f21fb7b31f.png

事件捕获

  • 当某个元素触发某个事件(如onclick),顶层对象document就会发出一个事件流,随着DOM树的节点向目标元素节点流去,直到到达事件真正发生的目标元素

  • 这个过程中,事件相应的监听函数是不会被触发的

  • 到达该目标元素节点后,触发该元素事件,如果没有绑定事件则不执行

事件冒泡

  • 从目标元素开始,往顶层元素传播
  • 途中如果有节点绑定了相应的事件处理函数,这些函数都会被触发。

捕获和冒泡的执行顺序

<div id='div1'>
  div1
  <div id='div2'>
    div2
    <div id='div3'>div3</div>
  </div>
</div>
let div1 = document.getElementById('div1')
let div2 = document.getElementById('div2')
let div3 = document.getElementById('div3')
div1.addEventListener('click'() => {
    console.log('div1 bubble')
})
div2.addEventListener('click'() => {
    console.log('div2 bubble')
})
div3.addEventListener('click'() => {
    console.log('div3 bubble')
})

div1.addEventListener('click'() => {
    console.log('div1 capture')
}, true)

div3.addEventListener('click'() => {
    console.log('div3 capture')
}, true)

div2.addEventListener('click'() => {
    console.log('div2 capture')
}, true)

  • 点击div3,发现结果为 div1 capture => div2caputre => div3 bubble => div3 bubble => div2 bubble=> div1 bubble 也就是说目标元素是先执行的冒泡,再执行的捕获。其余的都是先捕获后冒泡~ 这是因为目标元素是事件触发主体处于事件流中的目标阶段,处理事件的顺序是根据注册顺序来执行的

事件委托

  • 当大量子节点需要绑定事件处理的时候,管理起来较为麻烦,因此可以委托给父元素来进行统一的管理
  • 并且可以方便地动态添加和修改元素,不需要因为元素的改动而修改事件绑定

应用

ui里有多个li,当某个li点击的时候,打印出该li的值

  • 如果每个li添加点击事件当然也可以,但是不能统一管理,并且添加或者减少li元素的时候,可能会造成内存泄露

  • 解决方式是给ul添加点击事件

    <ul id="ul1">
        <li>111</li>
        <li>222</li>
        <li>333</li>
        <li>444</li>
    </ul>
    window.onload = function () {
        var oUl = document.getElementById('ul1');
        //这里给ul添加事件
        var oUl = document.getElementById('ul1');                
        oUl.addEventListener('click'function(e){
            if(e.target.nodeName === 'LI') {
                console.log(e.target.innerHTML)
            }
        })
    }

防止冒泡事件

  1. event.stopPropagation(); // 阻止了事件冒泡,但不会阻击默认行为
  2. event.preventDefault(); //阻止默认事件,比如a的跳转事件