【问题标题】:Event delegation on mouseover鼠标悬停时的事件委托
【发布时间】:2014-02-13 05:56:17
【问题描述】:
在创建点击事件时,我尽量只绑定一次——通常绑定到所有预期触发事件的节点共享的父节点。但是,我很好奇,鼠标悬停事件的最佳实践是什么:当结果是鼠标悬停时不断触发事件时,将事件绑定到父级是否仍然有意义?最有效的做法是什么?
【问题讨论】:
标签:
javascript
jquery
events
【解决方案1】:
为了结束这个问题,我将解释/引用这个答案中的一些相关注释:'Should all jquery events be bound to $(document)?',@Faust 在上面引用了这些注释:
事件委托并不总是让您的代码更快。除非您绑定到动态元素或大量元素,否则您应该将事件处理程序直接绑定到事件发生的对象,因为这样会通常效率更高。
更具体地说,这是需要或有利的事件委托的时候:
- 当您要捕获事件的对象是动态创建/删除时,您仍希望在它们上捕获事件,而不必在每次创建新事件处理程序时显式重新绑定事件处理程序。
- 当您有很多对象都需要完全相同的事件处理程序时(其中很多对象至少有数百个)。在这种情况下,在设置时绑定一个委托事件处理程序可能比绑定数百或更多直接事件处理程序更有效。请注意,委托事件处理在运行时的效率始终低于直接事件处理程序。
- 当您尝试捕获(在文档中的更高级别)发生在文档中任何元素上的事件时。
- 当您的设计明确使用事件冒泡和 stopPropagation() 来解决页面中的某些问题或功能时。
@jfriend00 的原创回答
【解决方案2】:
所以,我知道这个问题早已不复存在,但我想我不妨用一种方法来回答。
使用动态元素,您可以在父 div/容器上建立 mousemove 侦听器,然后在 div 中查询具有 :hover 属性的元素。
例如:
<div class="list-container">
<ul class="dynamic-list-content">
<!-- actual list elements provided by js -->
</ul>
</div>
然后:
var listContainer = document.querySelector('.list-container');
listContainer.addEventListener('mousemove', function(e) {
var hovered = listContainer.querySelector('li:hover');
// do something with the hovered element here.
});
请注意(正如您所提到的)这会触发很多,但不会超过您将 mousemove 事件侦听器添加到各个条目的情况。您可以使用数据属性、唯一 ID 等对此进行一些去抖动处理。不过,根据我的测试,它在 Chrome 中的性能非常好。