能否利用冒泡减少addEventListener

例如:
HTML:

<body>
    <div id="div_1"></div>
    <div id="div_2"></div>
</body>

js(1):

document.getElementById("div_1").addEventListener("click",function(){
    // 对div_1的操作
});

document.getElementById("div_2").addEventListener("click",function(){
    // 对div_2的操作
});

若利用冒泡。以上js(1)的实现也可以写成
js(2):

document.body.addEventListener("click",function(e){
    if(e.target.id == "div_1"){
        // 对div_1的操作
    }else if(e.target.id == "div_2"){
        // 对div_2的操作
    }
});

对于js(1)js(2),实际使用是否有差异,若有,两者哪个更优?

阅读 4.7k
9 个回答

题主真是一个爱思考的好少年,描述提到的冒泡捕获事件的方法,实际上就是所谓「事件委托」。
要讨论对单个节点的事件绑定和事件委托哪个更优,那必须得说明一下事件委托在解决什么问题。
首先,它绝不仅仅是在事件监听时为大家提供了一个新的选项。举个栗子,如果需要对选择器 .enabled 对应的所有元素绑定事件处理函数 foo(), 经典的做法便是不得不一个个遍历所有节点并绑定事件处理函数,如果解除绑定也是同样。为了保存每一个元素的事件绑定而带来的内存开销和遍历DOM造成的性能损失且不说,为新增加或者移除的元素添加或者移除绑定本身就是一件非常头疼的事情。而事件委托却没有此问题,无论是添加元素或者删除元素,无论是删除绑定还是新增绑定,开销都非常小。说到性能,如果还在担心冒泡本身是否会造成更大的开销,那不妨考虑一下,为每一个元素添加绑定的方法,难到就不会造成冒泡吗?换句话说,绑定与否跟冒泡与否是否有必然联系呢?
当然,使用何种技术本身是需要经过考量的,相信了解了细节的题主会处理好两种方案的关系。
题主如果有兴趣,可以看看 jQuery 事件委托的实现: https://github.com/jquery/jquery/blob/master/src/event.js#L794

对于复杂的网页结构来说,第一种性能更加,原生的getElementById获取对象是很快的;第二种虽然方便,减少了代码量,但是牺牲了性能,这实际上是一种事件委托,当你点击div1或者div2的时候,它都会去遍历dom数,寻找委托对象。

作为js小白的我喜欢js(1). 仅仅是因为觉得这样漂亮。

根据场景选择吧,针对js(2)不如给div添加class一个循环添加点击事件,还可以少了判断,性能会更好

js(1) 一次性绑定的时候比较好。
js(2) 比如你默认有3个元素带有class="a"绑定某个事件,而你再追加的时候第4个class="a"的元素是不会触发事件的,这时用(2)方便处理。

根据javascript高级程序设计中提高:
1、使用stoppropagation阻止事件冒泡
2、使用事件委托,其原理就是在父节点中添加事件,尽可能的使事件冒泡层次少。

这就是事件委托。很常用的。
委托有好处就是:当你触发的元素经常回add 和 remove时, 将事件绑定到父节点,就不用考虑子元素的add,remove。
有个不好的地方就是如果子元素执行了事件并禁止冒泡, 父节点是不会执行事件的。

JS中利用冒泡原理进行的事件委托;

可以去参看jQuery的两个函数:
.bind(eventType, fn) 和 on(eventType [, target], fn)
了解他们之间的区别;

.bind() 必须要元素存在才能进行事件绑定;
.on()可以利用事件冒泡原理进行事件处理, target可能还未创建;

新手上路,请多包涵

在你举得例子的情况下我觉得两者性能差别不大,如果div数量多了,那采用事件委托性能提升就比较明细了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏