javascript事件代理(delegate)原理解析

  什么是事件代理?首先得知道什么是事件,并且弄清楚事件流,才能真正明白事件代理原理。

一、什么是事件?

  javascript与HTML之间交互就是通过事件实现的,事件就是文档或浏览器窗口中发生的一些特定的交互瞬间。如onload、onclick、onmouseup、onmousedown... 。

二、事件流

  DOM(文档对象模型)结构是一个树型结构,当一个HTML元素产生一个事件时,该事件会在元素结点与根结点之间的路径传播,路径所经过的结点都会收到该事件,这个传播过程可称为DOM事件流。

  因为历史的原因,IE最开始实现实现事件流的方式:冒泡事件(event bubbling),Netscape提出了另外一种事件流方式:事件捕获(event capturing),不同的浏览器实现上有一些差别,用起来就有些繁琐。幸好现代浏览器都实现了W3C制定的"DOM2级事件","DOM2级事件"把事件流分为三个阶段,捕获阶段、目标阶段、冒泡阶段。

  网上借图:

  

三、什么是事件代理?

  前面做了这么多基础铺垫,那么现在理解事件代理就是很简单的事了。事件代理就是在祖先级DOM元素绑定一个事件,当触发子孙级DOM元素的事件时,利用事件流的原理来触发绑定在祖先级DOM的事件。听起来有点绕口,下面做一个简单的代码实现:

<!--省略html主体部分-->
<ul id="menu">
    <li><p><a>如果我被钗神翻牌,我就有一个成为大神的机会!</a></p></li>
    <li><p><a>如果我被钗神翻牌,我就有一个成为大神的机会!</a></p></li>
    <li><p><a>如果我被钗神翻牌,我就有一个成为大神的机会!</a></p></li>
    <!--中间省略1000000行-->
    <li><p><a>如果我被钗神翻牌,我就有一个成为大神的机会!</a></p></li>
</ul>  
// 获取祖先节点(这儿就获取ul),并为它添加一个click事件
document.getElementById("menu").addEventListener("click", function(e) {
  // 检查事件源e.targe是否为A
  if(e.target && e.target.nodeName.toUpperCase == "A") {
      console.log("钗神翻我牌,今晚就跟你走....");
  }
});

  浏览器的能力还是有限的,为了安全起见,系统分配给浏览器的内存也是有限的。特别是某些老版本的浏览器,如果在DOM上添加的事件过多,会导致网页的性能下降甚至崩溃。看我上面的ul下面的a节点就有1000004,如果真的为所有的a标签加一个事件,这个代价是很大的。用了事件代理,我们节约了1000003个事件,简直太强大了。

  一般浏览器触发事件都是在冒泡阶段,如果你想在捕获阶段触发事件你可以设置addEventListener第三个参数为true,addEventListener("click", function(e){}, true)。

总结:基础很重要,明白基础,原理就是那么简单!

  

原文地址:https://www.cnblogs.com/webhelper/p/5616477.html