js事件委托

我们收取快递有两种方法:一是在特定的地点等快递的到来,二是委托人代收。现实当中,我们大都采用委托的方案。而委托人接受的委托不止一份,他会判断收件人,从而发放到各自手中。这也就是js事件委托的通俗理解。

为啥要用事件委托?

一般来说,dom需要有事件处理程序,我们都会直接给它设事件处理程序就好了,那为什么要用事件委托呢?
独立典型的程序或许需要单独的处理程序,但是程序的结构越复杂庞大,就会有大量重复的程序事件。单独直接得处理程序,会严重影响工作的效率。可能,我们能用for循环等方法,遍历所以程序,但这会导致与dom节点的不断交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思想之一就是减少DOM操作的原因。
所以如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能

如何实现事件委托?

事件委托是利用事件的冒泡原理来实现的事件从最深的节点开始,然后逐步向上传播至最上层的事件。

网上常见的例子

 <ul id="ul">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>

我们需要把li的点击事件绑定到ul上

var ul = document.getElementById('ul')
ul.addEventListener('click', function() {})

这样我们就实现了委托,但是有出现了新的问题,如果ul内不止li,那么处于ul内的其他元素被点击时,事件也被触发了!
所以我们需要在触发事件前来一个判断

ul.addEventListener('click', function(e) 
           // 检查事件源e.targe是否为Li
           if (e.target && e.target.nodeName.toUpperCase == "LI") {

            // 真正的处理过程在这里
            console.log("点击成功")
          }
       }

这样就大功告成了?很遗憾,这种情况还存在一个严重的bug,如果元素在li中呢?那么事件就不会触发!比如这样

<ul id="ul">
    <li id="l1"><span>1</span></li>
    <li id="l2">2</li>
    <li id="l3">3</li>
    <li id="l4">4</li>
</ul>

那么该怎么做呢?我们需要再加一个判断,判断点击的元素的父辈元素中有没有li,如果有,就继续执行事件。

ul.addEventListener('click', function() {
                    let el = e.target
                    while (el && !el.matches(selector)) {
                        el = el.parentNode
                        if (element === el) {
                            el = null
                        }
                    }
                    if (el) {
                        console.log('执行回调函数')
                    }
                }

后记

我们发现问题,然后找出方法解决问题。并不代表事件的结束,我们所用的方法也许会带来其他的原题。多思考,多测试,不断完善。记住,现在得到的永远不是最佳答案。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容