事件委托,又称事件代理,是利用事件冒泡的特性,将本应该绑定在多个元素上的事件绑定在他们的祖先元素上,实现处理程序对多个子孙级元素的某类型事件管理。通俗来说,就是把任意个子孙级元素的响应事件的函数委托到另一个元素(通常为委托元素的祖先元素)。
DOM 树层级较深,绑定事件越多,浏览器内存占用越大,严重影响性能。
在 JavaScript 中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断地与 DOM 节点进行交互,访问 DOM 的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间。如果使用事件委托,就会将所有的操作放到 JavaScript 程序中,与 DOM 操作就只需要交互一次,这样就能大大减少与 DOM 的交互次数,提高性能。
每个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率就越大,自然性能就越差。
很多场景需要开发者通过 AJAX 或者用户动态增加或者去除列表项元素,那么在每一次改变的时候都需要重新给新增的元素绑定事件,给即将删去的元素解绑事件。
如果用了事件委托就没有这种麻烦了,因为事件是绑定在父层的,和目标元素的增减是没有关系的,执行到目标元素是在真正响应执行事件函数的过程中去匹配的。
所以使用事件在动态绑定事件的情况下是可以减少很多重复工作的。
使用事件委托能有效解决下列问题。
onfocus
、onblur
之类的事件本身没有事件冒泡机制,所以无法使用事件委托mouseover
、mousemove
这样的鼠标、滚轮等事件,虽然有事件冒泡,但是只能不断通过位置去计算定位,对性能消耗高,因此也是不适合事件委托的使用事件委托的注意事项:
<body>
元素上进行绑定(事件委托的原理离不开 DOM 的查找,而浏览器太多层级的查找非常耗性能)事件委托影响性能的因素:
结合这两点,可以在必须使用事件委托的场景下,以如下原则优化。
<body>
元素上,进行绑定<body><ul class="list"><li>1</li><li>2</li><li>3</li><!-- 还有很多 --></ul><script type="text/javascript">const list = document.querySelector('.list');list.addEventListener('click',function(e) {let e = e || window.event;let target = e.target || e.srcElement;// 关键判断条件const index = [].indexOf.call(target.parentElement.children, target);console.log(index);},false);</script></body>
参考文章: