事件委托

61 阅读1分钟

一、什么是事件委托

提到事件委托,我们必须先了解事件流中的事件捕获和事件冒泡。

事件捕获就是从DOM的根元素开始去执行对应的事件,执行过程是从外到里。

事件冒泡就是从文档树中最深的节点开始触发,然后向上传播至没有那么具体的文档,执行过程是从里到外。

<ul>
    <li>first child</li>
</ul>
    <script>
        const li = document.querySelector('li')
        const ul = document.querySelector('ul')
        const body = document.body

        li.addEventListener('click', function () {
            console.log('我是子元素')
        })
        ul.addEventListener('click', function () {
            console.log('我是父元素')
        })
        body.addEventListener('click', function () {
            console.log('我是body')
        })
            document.addEventListener('click', function () {
            console.log('我是document')
        })
    </script>

效果如下:

propagation.gif

当我点击子元素的时候,就触发了事件冒泡机制,从 li 开始触发到 ul 再到 body 最后到 document。

事件委托就是利用事件冒泡,把原本要绑定在子元素的响应事件委托给父元素,通过父元素监听子元素。

二、使用场景

当我们要给n个按钮添加点击事件时,最笨的方法就是给每个按钮都添加,此方法耗时且麻烦。但是如果委托给父元素,让父元素担当事件监听的职务,则通过事件冒泡就可以获取到所有子元素。

    <ul>
        <li>first child</li>
        <li>second child</li>
        <li>third child</li>
        <li>fourth child</li>
        <li>fifth child</li>
    </ul>
    <script>
        // 点击每个小li 被点击的li消失
        // 1. 获得父元素
        const ul = document.querySelector('ul')
	// 2. 利用事件委托,将点击事件委托给父元素
        ul.addEventListener('click', function (e) {
            // e.target: 判断点的是哪一个元素(标签)
            // tagName: 标签名字
            // 3. 找到触发的元素
            if (e.target.tagName === 'LI') {
                e.target.style.display = 'none'
            }
        })
    </script>

效果如下:

listen.gif

其中,e.target 是事件源,获取 e.target 以查看事件实际发生的位置并进行处理;tagName 是标签名字,注意必须得大写。

三、优点

  1. 减少事件注册的次数,节省内存占用,提高程序的性能
  2. 新增子对象时也无需再次对其绑定