JavaScript与HTML之间的交互是通过事件来实现的,事件就是当文档或者浏览器窗口发生一些特定的交互瞬间,事件流是指从页面中接收事件的顺序。IE和Netscape开发团队提出,当你点击页面上的按钮时,你也同时点击了按钮的容器元素,甚至也点击了整个页面,但是,对于事件流,这两个团队提出了两个完全相反的事件流概念,IE认为,事件流是冒泡流,而Netscape认为事件流是捕获流。
事件冒泡
事件冒泡即由最具体的元素(文档中嵌套层次最深的节点)到最不具体的元素(文档)。
HTML结构如下
<div id="parent">
<div id="child"></div>
</div>
JS代码
// DOM0级
child.onclick=function(){
console.log('child')
}
parent.onclick=function(){
console.log('parent')
}
document.onclick=function(){
console.log('body')
}
document.onclick=function(){
console.log('document')
}
// DOM2级
child.addEventListener('click',function(e){
console.log('child');
},false)
parent.addEventListener('click',function(e){
console.log('parent');
},false)
document.body.addEventListener('click',function(e){
console.log('body');
},false)
document.addEventListener('click',function(e){
console.log('document');
},false)
当点击child时,可以看到控制台

当点击parent时

当点击body时

当点击document时

也就是说,click事件首先在child元素上发生,然后沿DOM树向上传播,在parent元素上发生,最后传播到document上。如果只点击parent,就从parent沿着DOM树向上传播,直到document。

事件捕获
事件捕获是不太具体的节点应该最早接收事件,而最具体的节点最后接收事件。
// DOM2级
child.addEventListener('click',function(e){
console.log('child');
},true)
parent.addEventListener('click',function(e){
console.log('parent');
},true)
document.body.addEventListener('click',function(e){
console.log('body');
},true)
document.addEventListener('click',function(e){
console.log('document');
},true)
当点击child时

当点击parent时

当点击body时

当点击document时

在事件捕获的过程中,click事件首先在document上发生,然后沿DOM树向下传播,最后传播到child上。如果只点击parent,就从document沿着DOM树向下传播,直到自己被点击。

可以根据addEventListener()接收的第三个参数来规定是否选择事件冒泡或者事件捕获,true表示遵循事件捕获,false或者不传入参数表示遵循事件冒泡,建议使用事件冒泡,特殊情况下再使用事件捕获。
DOM2事件流
DOM2事件流包含了三个阶段:事件冒泡阶段,处于目标阶段,事件捕获阶段,首先发生的是事件捕获,为截获事件提供了机会,然后是事件的目标阶段接收阶段,最后一个阶段是冒泡阶段,可以在这个阶段对事件作出相应,如图

网友评论