JavaScript世界中的一个很热门的方法论就是事件代理,它可以使我们避免向特定的元素节点绑定事件监听,而是绑定在了一个父级节点。
这个事件监听回对冒泡上来的事件进行分析,找到所匹配的子元素。
这个概念其实很简单,但是还有很多人不太清楚事件代理是如何工作的。
本文将简要解释事件代理是如何工作的,同时提供一个基本的事件代理的实现。
举个栗子
比如说我们有一个父级ul
元素,同时有一些子级元素节点:
|
|
需求是当每个元素被点击时,我们需要为每一个独立的li
元素添加一个事件监听器,来处理相应的事件。
问题是:
如果这些li
元素需要被频繁的从列表中添加和移除时,添加和移除事件监听器很麻烦,特别是当执行这些添加和移除的代码是app中其他地方的。
较好的解决方案是,把事件监听器添加到li
的父级节点ul
上,但是这样一来,我们怎么知道是哪个元素被点击了呢?
答案:
当事件冒泡到了ul
元素时,我们手动检查事件对象的目标(target)属性,获取到真正被点击的节点。
下面是一个非常简单和基础的js代码片段来解释什么是事件代理:
|
|
上面的代码首先给父级节点添加了click
事件监听器,当被触发时,检查事件的目标元素来确定是不是想要操作的对象:
如果是,则运行相对应的代码;如果不是,则该事件就会被忽略。
这个例子是有点儿简单,但足以说事件代理的原理。可能在判断事件目标元素时有些负责,需要各种选择器来辅助。
下面看jQuery中的用法,使用.on
函数,结合其强大的元素选择器,就能方便的实现事件代理。
|
|
最后总结一下,事件代理使用的场景和需要注意的地方。
- 待绑定的对象元素是动态的,需要频繁的添加或者删除等;
- 待绑定的元素很多,比如一个100行的Table,需要对tr绑定事件;
- 被绑定的父级对象离目标对象的层级越少越好,否则会有性能问题,尽量不要直接绑定到document或者body上
- 选择器越简单越好,会提升性能
- 事件类型要注意是能冒泡的,比如
focus
和blur
本身是不会冒泡的