盒子
盒子

事件代理是什么?

开篇

JavaScript事件代理,又名为事件委托,在浏览器环境里,dom树上发生,同一管理某一类型的事件。实现原理是用了事件冒泡的机制来实现的。
那首先讲一下事件冒泡和事件捕获。

事件冒泡和事件捕获。

事件冒泡和事件捕获是2个完全相反的概念,都是被提出用于解决页面中事件流(事件发生顺序)的问题。

1
2
3
<div id="outer">
<p id="inner">Click me!</p>
</div>

举个例子,上述的dom结构下,当p被点击后。
事件冒泡是由最具体的元素开始,一直向上传播。知道document对象。所以例子中发生click事件的顺序是
p->div->body->html->document

事件捕获则是由最外层开始。直到具体的元素。所以例子中的顺序就是document->html->body->div->p
“DOM2级事件”中规定的事件流同时支持了事件捕获阶段和事件冒泡阶段,想要开启事件捕获可以指定addEventListener方法中的第3个参数为true。

事件代理

那么事件代理,其实就是使用事件冒泡的机制,将发生在具体的元素上的事件,统一到父级处理。

1
2
3
4
5
6
7
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>

如上面的代码,将事件注册在li上就需要注册5个。但是注册在ul上,然后处理,就只需一个监听器,从而实现了诸多好处,譬如可以方便的动态添加/删除元素,不需要还要在再为其修改事件绑定。

应用

这也是在查询事件代理相关资料时候,发现了原来React的事件系统,使用了事件委托,命名为SyntheticEvent(合成事件)。它并不会把事件处理函数直接绑定到真实的节点上,而是把所有事件绑定到结构的最外层,使用一个统一的事件监听器,这个事件监听器上维持了一个映射来保存所有组件内部的事件监听和处理函数。当组件挂载或卸载时,只是在这个统一的事件监听器上插入或删除一些对象;当事件发生时,首先被这个统一的事件监听器处理,然后在映射里找到真正的事件处理函数并调用。这样做简化了事件处理和回收机制,效率也有很大提升。