基础知识
1.操作系统最先知道用户点击了鼠标,浏览器次之
2.child 被点击了,意味着 parent 也被点击了
3.如果我同时监听了 child 和 parent,那么谁先通知我?这是个问题。
捕获阶段
parent 先通知,child 后通知
1 | <body> |
2 | <div class="parent"> |
3 | <div class="child"></div> |
4 | </div> |
5 | <script> |
6 | var parent = document.getElementsByClassName("parent")[0]; |
7 | var child = document.getElementsByClassName("child")[0]; |
8 | child.addEventListener('click',function(){ |
9 | console.log("child") |
10 | },true) |
11 | parent.addEventListener('click',function(){ |
12 | console.log("parent"); |
13 | },true) |
14 | document.body.addEventListener('click',function(){ |
15 | console.log("body"); |
16 | },true) |
17 | </script> |
18 | </body> |
当点击chlid时,控制台依次显示如下:

捕获从window开始,到document,再到html,再到body,再到被点击元素的祖先元素,再到被点击元素的父元素,最后到被点击的元素。一级一级往下找,有监听事件就执行。用一幅图描述,如下:

Capture Phase就是捕获阶段,只有早期 Navigator 默认支持它,所以我们一般不用「捕获阶段」。Bubbling Phase是冒泡阶段,一般用「冒泡阶段」。
冒泡阶段
child 先通知,parent 后通知
IE 一开始就支持冒泡。
1 | <body> |
2 | <div class="parent"> |
3 | <div class="child"></div> |
4 | </div> |
5 | <script> |
6 | var parent = document.getElementsByClassName("parent")[0]; |
7 | var child = document.getElementsByClassName("child")[0]; |
8 | child.addEventListener('click',function(){ |
9 | console.log("child") |
10 | }) |
11 | parent.addEventListener('click',function(){ |
12 | console.log("parent"); |
13 | }) |
14 | document.body.addEventListener('click',function(){ |
15 | console.log("body"); |
16 | }) |
17 | </script> |
18 | </body> |
当点击chlid时,控制台显示如下:

冒泡跟捕获相反,从被点击的元素开始,到被点击元素的父元素,再到被点击元素的祖先元素,再到body,再到html,再到document,最后到window,一级一级往上冒,有监听事件就执行。