一: 事件冒泡
IE提出的事件流叫做事件冒泡,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点,看一下以下示例:
<div onclick="divClick()">
<button onclick="btn()">
<p onclick="p()">点击冒泡</p>
</button>
</div>
<script>
function p(){
console.log('p标签被点击')
}
function btn(){
console.log("button被点击")
}
function divClick(event){
console.log('div被点击');
}
</script>
点击P元素,输出:
p标签被点击
button被点击
div被点击
p=>button=>div=>body
二:事件捕获
事件捕获流的思想是不太具体的DOM节点应该更早接收到事件,而最具体的节点应该最后接收到事件,针对上面同样的例子,点击按钮,那么此时click事件会按照这样传播:(下面我们就借用addEventListener的第三个参数来模拟事件捕获流)第三个参数为true为捕获,否则冒泡。
<div>
<button>
<p>点击捕获</p>
</button>
</div>
<script>
var oP=document.querySelector('p');
var oB=document.querySelector('button');
var oD=document.querySelector('div');
oP.addEventListener('click',function(){
console.log('p标签被点击')
},true);
oB.addEventListener('click',function(){
console.log("button被点击")
},true);
oD.addEventListener('click', function(){
console.log('div被点击')
},true);
</script>
结果:
div被点击
button被点击
p标签被点击
小技巧:
将事件监听器设置在父节点上,并将事件监听器气泡的影响设置为每个子节点,而不是为了每个子节点单独设置事件监听器。比如一个ul中的每个li上的图片都有同样的点击事件,可在ul上设置监听器
function funA(e){
console.log(e.target.src);//e.target为事件发生时的对象,即某个li
e.stopPropagation(); //不会在气泡链上进一步扩大
}
ul.addEventListener('click',funA,true);