DOM 事件委托

示例

事件委托是一个过程,它使我们能够避免将事件侦听器添加到特定节点;而是将事件侦听器添加到父节点。此机制利用事件传播/冒泡在DOM中更高级别的元素/节点处处理事件,而不是使用事件起源于其的元素。例如,认为我们需要为以下列表元素添加事件:

<ul id="container">
    <li id="item-1" class="new">Item 1</li>
    <li id="item-2">Item 2</li>
    <li id="item-3">Item 3</li>
</ul>

我们需要添加click处理程序,并且基本上可以使用循环将侦听器添加到每个元素,但是可以想象,我们想动态添加元素。因此,我们在加载DOM时注册所有事件处理程序,并且在DOM初始化并为每个元素注册所有事件处理程序后,新插入到上述元素中的元素UL将不会在点击时做出响应,因为该元素在DOM中不存在我们已经注册了click事件监听器。

因此,为克服此问题,我们可以利用事件委托。这意味着,li我们可以将事件侦听器绑定到其父UL元素,而不是将侦听器注册到每个元素本身,例如:

document.getElementById("container").addEventListener("click", function(e) {
    console.log("项目清单 " e.target.id, " was clicked!");
});

由于默认情况下事件会传播(向上冒泡),因此单击任何LI元素都会使该UL元素也触发相同的事件。在这种情况下,我们可以e在函数中使用参数,该参数实际上是事件对象,并且包含有关事件的有用信息,包括启动事件的原始元素。因此,例如,我们可以使用以下内容:

document.getElementById("container").addEventListener("click", function(e) {

    // 如果本身是UL,则无需采取任何措施
    if(e.target.nodeName == 'UL') return false;

    if(e.target.classList.contains('new')) {
        console.log("项目清单 " e.target.id, " was clicked and it's new!");
    }
});

因此,很明显,e(Event Object)允许我们检查源元素(e.target),并且可以UL在DOM加载后轻松地将新元素注入到元素中,并且只有一个委派的事件处理程序将处理parent UL,这也减少了内存消耗,因为我们为所有元素仅声明了一个函数。