JavaScript与HTML之间的交互是通过事件来实现的,事件就是当文档或者浏览器窗口发生一些特定的交互瞬间,事件流是指从页面中接收事件的顺序。IE和Netscape开发团队提出,当你点击页面上的按钮时,你也同时点击了按钮的容器元素,甚至也点击了整个页面,但是,对于事件流,这两个团队提出了两个完全相反的事件流概念,IE认为,事件流是冒泡流,而Netscape认为事件流是捕获流。
事件冒泡
事件冒泡即由最具体的元素(文档中嵌套层次最深的节点)到最不具体的元素(文档)。
HTML结构如下
1 2 3
| <div id="parent"> <div id="child"></div> </div>
|
JS代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| child.onclick=function(){ console.log('child') } parent.onclick=function(){ console.log('parent') } document.onclick=function(){ console.log('body') } document.onclick=function(){ console.log('document') } 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。
事件捕获
事件捕获是不太具体的节点应该最早接收事件,而最具体的节点最后接收事件。
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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事件流包含了三个阶段:事件冒泡阶段,处于目标阶段,事件捕获阶段,首先发生的是事件捕获,为截获事件提供了机会,然后是事件的目标阶段接收阶段,最后一个阶段是冒泡阶段,可以在这个阶段对事件作出相应,如图