事件捕获、事件冒泡、事件委托
1. 事件流
介绍事件冒泡和事件捕获之前先介绍一下前端中的事件流,什么叫事件流呢,事件流描述的是页面中事件的发生顺序,分为三个阶段,事件捕获阶段,处于目标阶段,事件冒泡阶段,下面就来详细介绍一下事件捕获和事件冒泡。
2. 事件捕获
当鼠标点击或者触发一个dom事件时(被触发dom事件的这个元素叫事件源),浏览器会从根节点向事件源进行事件传播(从外到内)
<body>
<div>
<p></p>
</div>
</body>
//事件传播的顺序为document => html => body => div => p
3. 事件冒泡
当鼠标点击或者触发dom事件时,浏览器会从事件源向根节点进行事件传播(从内到外)
<body>
<div>
<p></p>
</div>
</body>
//事件传播的顺序为p => div => body => html => document
如果当点击了子元素后,不想触发父元素事件,可进行阻止事件冒泡,阻止事件冒泡的方式有两种:
-
给子元素添加event.stopPropagation(),这是在标准浏览器中遵循W3C标准时使用,如果是IE等低版本的浏览器需要使用cancelBubble()
-
在事件处理函数中返回false
这两种方式的区别在于,return false不仅阻止了事件往上冒泡,还阻止了事件本身的默认事件,而 event.stopPropagation只阻止了事件往上冒泡,不阻止事件本身的默认行为
-
event.target == event.currentTarget,让触发事件的元素等于绑定事件的元素也可以阻止事件冒泡
阻止事件默认行为的方法:
- event.preventDefault()[W3C标准浏览器下] / returnValue() [IE低版本浏览器下]
- return false,在事件处理函数中返回false
4. 如何设置事件处理函数在事件捕获时触发还是事件冒泡时触发
window.addEventListener(),里面可以传递三个参数,第一个参数为事件的名字,例如click、scroll、mousemove、mouseover等等,第二个参数为事件触发函数,这两个参数为必传参数,第三个参数为布尔值,true / false,当为true的时候代表事件冒泡,当false的时候为事件捕获,默认情况下为true,事件冒泡第三个参数可传可不传。
5. 事件委托
事件委托又叫做事件代理,是事件冒泡和事件捕获的运用。
一般来讲,将一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,当事件响应到需要绑定的元素身上时(事件捕获),会通过事件冒泡机制,从而触发它的外层元素的绑定事件上,然后在外层元素上执行事件响应函数,可以达到减少内存消耗的效果。
举个例子吧
<ul>
<li>11111</li>
<li>22222</li>
<li>33333</li>
</ul>
let ul = document.getElementsByClassNames('ul')[0];
ul.addEventListener('click',function(e){
if(e.target.nodeName !== 'LI'){
return;
}
let lis = Array.from(ul.children);
let index = lis.indexOf(e.target);
let text = lis[index].innerText;
console.log(text);
})
//这样就可以实现,当点击某一个li的时候,控制台就会打印出li里面的文本内容,将li的点击事件绑定到它的父元素ul身上,让父元素代替执行事件响应函数,这样,当ul里面有很多的li的时候,也不用进行全部遍历,减少了内存的消耗。