最近参考了网上很多关于JS事件捕获和事件冒泡机制的文章,以下内容为个人对之理解,方便日后查阅。
事件捕获和事件冒泡是啥?
事件捕获和事件冒泡分别是Netscape和IE对DOM事件产生顺序的描述。Netscape认为DOM接收的事件最先应该是window接收,然后再一节一节往下,最后才是具体的元素接收到事件,即:事件捕获。而IE则认为DOM事件应该由具体元素最先接收事件,然后再一节一节往上,最后再由window接收事件,即:事件冒泡。最后W3C将两种方案做了统一,即:把DOM事件分为两个阶段,事件捕获阶段和事件冒泡阶段,例如:当页面某一个元素被点击,首先是事件捕获阶段,window最先接收事件,然后一节一节往下捕获,最后由具体元素接收,然后再由具体元素一节一节往上,最后window会再次接收事件,以下为DOM事件流示意图:
这样当页面上一个对象触发某个事件,我们会有两次机会对其进行操作!虽然DOM2级事件规范中要求事件捕获过程中不会涉及事件目标,但是各高版本浏览器中都会在事件捕获过程中触发对象事件。
在JS事件学习中常常会看到或者听到事件代理(事件委托)这个说法,那么,什么是事件代理(事件委托)?
什么是事件代理(事件委托)?
看上去很抽象,可以用一个例子来简单说明其原理:我们在网上购物,我们会留下一个具体地址来接收包裹,但是由于快递员不能每一件都亲自送到我们手中,所以,快递代收站出现了,快递员只需要把快递放在快递站,然后再继续派送其他快递,我们只需要在适当的时机到快递站取快递即可。在这个过程中,包裹就是某个事件,快递员派送的过程就是时间捕获的过程,适当的时机即事件捕获到来最底层的具体得到元素,我们去快递站取快递就是时间冒泡的过程,所以事件代理(事件委托)就是利用事件冒泡原理在快递站(父元素)接收我们的快递(事件),然后我们再去快递站取款地(事件冒泡)。js中提供了event对象,在这个对象中有个target属性,通过target属性我们就能知道具体是哪个元素触发了事件。
为什么是要使用事件代理(事件委托)?
为什么会有快递站呢?当然是提高效率,如果快递员每一件播过都亲自送到用户手中,那效率得多低。事件代理也如此,我们操作DOM的是代价的,应该尽量避免频繁的操作DOM元素,如果我们给DOM每一个元素都添加事件,理论上没有任何问题,但是从效率,优化上来讲显得过于麻烦低效。
事件代理简单DEMO:
<style> 2 li { 3 width: 100px; 4 height: 50px; 5 background-color: pink; 6 } 7 div { 8 width: 80%; 9 height: 80%; 10 background-color: red; 11 } 12 span { 13 display: block; 14 width: 80%; 15 height: 80%; 16 background-color: cyan; 17 18 } 19 a { 20 display: block; 21 width: 80%; 22 height: 80%; 23 background-color: greenyellow; 24 } 25 </style> 26 </head> 27 <body> 28 <ul> 29 <li> 30 <div> 31 <span> 32 <a href="javascript:;">A</a> 33 </span> 34 </div> 35 </li> 36 <li>2</li> 37 <li>3</li> 38 <li>4</li> 39 <li>5</li> 40 <li>6</li> 41 </ul> 42 <script> 43 var ul = document.querySelector(‘ul‘); 44 ul.addEventListener(‘click‘, function (e) { 45 console.log(e.target); 46 47 }); 48 </script>
以上代码只对ul进行了事件监听,但是当我们分别点击不同元素时,即使该元素没有添加事件监听,同样会在控制台上显示我们点击了这个元素,这就是事件代理(事件委托)。
原文:https://www.cnblogs.com/li-qiang-blog/p/10807078.html