概述
在理解事件委托之前,我们需要先学习事件捕获和事件冒泡。在DOM树结构中,当一个事件发生时,事件是从根节点向叶节点逐级传递的,事件到达目标节点后,又逐级传递到根节点。
- 事件从根节点传递到叶子节点的过程,称为事件捕获(Event Capture)
- 事件从叶子节点传递到根节点的过程,称为事件冒泡(Event Bubble)
基本示例
1 | <body> |
例如在上面的代码中,点击span时,事件的传递顺序就是:body -> div -> span -> div -> body。其中body -> div -> span即事件捕获,span -> div -> body即事件冒泡。目前处理事件的时机一般都在事件冒泡阶段。
注:先捕捉后冒泡,W3C规定的标准,但是早期浏览器有些相反。
事件委托
事件委托(Event Delegation)是JavaScript中一种很常用的技术。简单地讲,就是当我们需要给一个DOM节点添加事件的时候,我们不直接讲事件绑定到该节点上,而是将事件绑定到某个指定的父节点上去。当目标事件发生时,让业务逻辑在事件冒泡直到指定的父节点时,对比事件目标之后,再去做相关处理。事件委托,就是这样一种处理事件的方法。
为什么要事件委托
也许你会觉得这太麻烦了,我为什么不直接把事件处理放到目标DOM节点上去,而要特地拐弯抹角地去把事件处理放到父节点上去呢。在前端发展迅猛的今天,DOM操作变得越来越频繁和复杂。DOM结构也经常发生动态变化,当频繁添加或者删除DOM节点时,如果也还需要手动去为每一个节点绑定事件,代码量不仅巨大且及其难以维护,这种情况下直接绑定事件到目标节点将是灾难性的。
示例
假定你有DOM结构如下。
1 | <ul id="parent-list"> |
你需要响应每个LI的点击事件。当UL下的LI不固定,经常新增或者删除时,直接为LI绑定事件显然是不可取的。
使用事件委托的话,我们应该在UL上绑定事件。这里使用Element.matches API来判定是否是目标事件。
1 | // Get the element, add a click listener... |
一般来说,我们在实际开发应用的时候,很少会直接用写原生的JavaScript实现的事件委托,这里也推荐用各种三方JavaScript库来实现。以Jquery为例,它封装了更多功能,包括了目标节点确认等。