事件捕获和事件冒泡
事件捕获和事件冒泡是一个相反的过程
在某个标签触发某个事件时,首先会从根节点开始遍历找到这个节点的父元素们,先发生捕获事件,找到并指执行然后开始冒泡
顺序可以参考下下面的:
捕获:document -> html -> body -> div -> p
冒泡:p -> div -> body -> html -> document
可以这么形容,当你你点击p之后,就好像向水里面扔了一个苹果,由于物理的一些原因,苹果首先会沉下一段距离(捕获),然后苹果会因为浮力浮出水面(冒泡)
而在进行捕获或者冒泡的过程中,如果对应的节点绑定了事件,那么在对应的流程中就会触发
div1.addEventListener('click',clickFunc) //冒泡
div2.addEventListener('click',clickFunc,false) //冒泡
div3.addEventListener('click',clickFunc,true) //捕获
div4.addEventListener('click',clickFunc,true) //捕获
比如这里我点击div3,那么开始从根节点开始遍历
到了div1有一个冒泡事件,但是现在是捕获的环节,所以不执行
然后div2同样的不执行
div3发现有一个捕获事件所以执行
div4事件本身,所以执行
然后开始冒泡
开始上浮,到div2 和 div1 时都会执行
<div id="div1" style="background-color: red;">
div1
<div id="div2" style="background-color: royalblue;">
div2
<div id="div3" style="background-color: violet;">
div3
<div id="div4" style="background-color: green;">
这就是一个点击的时间
</div>
</div>
</div>
</div>
但是
我点击div4,触发了许多事件,但是在每个事件打印event.target的值都是div4
事件处理程序中的this值始终等于currentTarget的值,指向的是绑定到的那个元素
点击谁this绑定的就是谁,无论在哪里触发事件(通过冒泡和捕获)
注意:这里的事件,只有在同类型事件时才会触发
比如我将div2的事件改成mouseout,鼠标离开那个区域时触发
现在我点击div4,但是冒泡事件不会触发,但是当我的鼠标离开div4时div2绑定事件便会触发
我自己的理解就是捕获和冒泡,其实就是在另一个节点的事件里(父节点或者父父节点再往上),在绑定节点的作用域里触发自身定义的事件,所以便有了事件委托
事件委托(代理)
看下面的代码:
<ul id = 'ul'>
<li>第1个li</li>
<li>第2个li</li>
<li>第3个li</li>
<li>第4个li</li>
<li>第5个li</li>
</ul>
let ul = document.getElementById('ul');
ul.addEventListener('click',clickFunc,false) //默认是冒泡
//点击li时候时候不会触发,然后会冒泡往上层,遇到ul标签绑定了事件,但是event的target仍然指向的是点击的元素
// 事件处理程序中的this值始终等于currentTarget的值,指向的是绑定到的那个元素
function clickFunc(ev) {
console.log(ev);
var ev = ev || window.event; //兼容ie浏览器
var oLi = ev.srcElement || ev.target;
console.log(oLi);
if(oLi.nodeName.toLowerCase() === 'li'){
alert(oLi.innerText)
}
}
如果对于每个li我们都绑定一个函数,无论时手动还是通过循环都很消耗资源
我们利用冒泡的机制,因为ul是每个li的父节点,所以在这些li被点击时,产生的冒泡肯定都会经过ul
在ul里获取当前的事件target就可以拿到li里面的文本内容,从而实现每个li的点击事件