事件捕获和事件冒泡
首先我们先了解什么是事件流?
事件流描述了页面接收事件的顺序, 先捕获(由外到内),到事件源,在冒泡(由内到外)。
三个阶段:捕获,事件源,冒泡
1.事件捕获(Netscape事件流)
事件捕获的意思是最不具体的节点应该最先收到事件,而最具体的节点应该最后收到事件。事件捕获实际上是为了在事件到达最终目标前拦截事件。(由外到内)
案例:
<style>
#div1 {
width: 400px;
height: 400px;
border: 1px solid red;
text-align: center;
}
#p1 {
display: inline-block;
width: 200px;
height: 200px;
border: 1px solid red;
text-align: center;
}
#a1 {
display: inline-block;
width: 100px;
height: 100px;
border: 1px solid red;
}
</style>
<script>
window.onload = function () {
var div = document.querySelectorAll("div,p,a");
// console.log(div[0]);
function divClick() {
console.log(this.tagName + '被点击了');
}
for (var key of div) {
key.addEventListener("click", divClick,true);//监听事件的第三个参数为true时是事件捕获,默认值为false(事件冒泡)
}
// div[0].removeEventListener("click", divClick, true);
};
</script>
</head>
<body>
<div id="div1">
我是div
<p id="p1">
我是p
<a id="a1">我是a</a>
</p>
</div>
</body>
效果图:
点击最里面的a标签时,由最外面的div开始往里寻找目标标签a,因为全部元素都被绑定了点击事件,所以由外到内一次触发。
由于旧版本浏览器不支持,因此实际当中几乎不会使用事件捕获。通常建议使用事件冒泡,特殊情况下可以使用事件捕获。
即使事件源没有绑定相关事件,也会发生事件捕获和冒泡。(例子:如果上述的a标签没有绑定点击事件,被点击的时候也会发生事件捕获)
2.事件冒泡(IE事件流)
IE 事件流被称为事件冒泡,这是因为事件被定义为从最具体的元素(文档树中最深的节点)开始触发,然后向上传播至没有那么具体的元素(文档)。(由内到外)
案例:
<style>
#div1 {
width: 400px;
height: 400px;
border: 1px solid red;
text-align: center;
}
#p1 {
display: inline-block;
width: 200px;
height: 200px;
border: 1px solid red;
text-align: center;
}
#a1 {
display: inline-block;
width: 100px;
height: 100px;
border: 1px solid red;
}
</style>
<script>
window.onload = function () {
var div = document.querySelectorAll("div,p,a");
// console.log(div[1]);
function divClick() {
console.log(this.tagName + "被点击了");
}
for (var key of div) {
key.addEventListener("click", divClick, false);//第三个参数为false,为事件冒泡
}
// div[0].removeEventListener("click", divClick, false);
};
</script>
</head>
<body>
<div id="div1">
我是div
<p id="p1">
我是p
<a id="a1">我是a</a>
</p>
</div>
</body>
效果图如上,就不放了。
点击最里面的a标签,最先触发 click 事件。然后,click 事件沿DOM 树一路向上,在经过的每个节点上依次触发,直至到达 document 对象,所以div,p触发点击事件。
事件冒泡可能会使绑定相同事件的父子元素一同触发,会达不到我们想要的效果,所以有时我们要阻止冒泡事件。
阻止冒泡事件
使用阻止事件冒泡之前,先要知道DOM事件默认提供的一个对象,HTML DOM Event对象。
Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。
事件通常与函数结合使用,函数不会在事件发生前被执行!
event.stopPropagation()
直接在对应方法中使用event.stopPropagation()便可阻止事件冒泡。
阻止默认事件发生
用于阻止特定事件的默认动作。比如,链接的默认行为就是在被单击时导航到 href 属性指定的 URL或是修改表单提交的默认事件。
event.preventDefault()
直接在对应方法中使用event.preventDefault()。