DOM事件流的三个阶段

以程序的角度说,流是具有方向的数据。

事件流之事件冒泡与事件捕获

在浏览器发展的过程中,开发团队遇到了一个问题。那就是页面中的哪一部分拥有特定的事件?
可以想象画在一张纸上的一组同心圆,如果你把手指放在圆心上,那么你的手指指向的其实不是一个圆,而是纸上所有的圆。放到实际页面中就是,你点击一个按钮,事实上你还同时点击了按钮所有的父元素。
开发团队的问题就在于,当点击按钮时,是按钮最外层的父元素先收到事件并执行,还是具体元素先收到事件并执行?所以这儿引入了事件流的概念。

事件流所描述的就是从页面中接受事件的顺序。

因为有两种观点,所以事件流也有两种,分别是事件冒泡和事件捕获。现行的主流是事件冒泡。

事件冒泡

事件冒泡即事件开始时,由最具体的元素接收(也就是事件发生所在的节点),然后逐级传播到较为不具体的节点。举个栗子,就很容易明白了。

 
  1. <!DOCTYPE html>

  2. <html lang="en">

  3. <head>

  4. <meta charset="UTF-8">

  5. <title>Event Bubbling</title>

  6. </head>

  7. <body>

  8. <button id="clickMe">Click Me</button>

  9. </body>

  10. </html>

然后,我们给button和它的父元素,加入点击事件。

 
  1. var button = document.getElementById('clickMe');

  2.  
  3. button.onclick = function() {

  4. console.log('1. You click Button');

  5. };

  6. document.body.onclick = function() {

  7. console.log('2. You click body');

  8. };

  9. document.onclick = function() {

  10. console.log('3. You click document');

  11. };

  12. window.onclick = function() {

  13. console.log('4. You click window');

  14. };

效果如图所示:

在代码所示的页面中,如果点击了button,那么这个点击事件会按如下的顺序传播(Chrome浏览器):

  1. button

  2. body

  3. document

  4. window

也就是说,click事件首先在<button>元素上发生,然后逐级向上传播。这就是事件冒泡。

事件捕获

事件捕获的概念,与事件冒泡正好相反。它认为当某个事件发生时,父元素应该更早接收到事件,具体元素则最后接收到事件。比如说刚才的demo,如果是事件捕获的话,事件发生顺序会是这样的:

  1. window

  2. document

  3. body

  4. button

当然,由于时代更迭,事件冒泡方式更胜一筹。所以放心的使用事件冒泡,有特殊需要再使用事件捕获即可。

DOM事件流

DOM事件流包括三个阶段。

  1. 事件捕获阶段

  2. 处于目标阶段

  3. 事件冒泡阶段

如图所示(图片源于网络,若侵权请告知):

1. 事件捕获阶段

也就是说,当事件发生时,首先发生的是事件捕获,为父元素截获事件提供了机会。
例如,我把上面的Demo中,window点击事件更改为使用事件捕获模式。(addEventListener最后一个参数,为true则代表使用事件捕获模式,我的理解也就是把事假绑定在了事件捕获阶段,false则表示使用事件冒泡模式,把事件绑定在了事件冒泡阶段。不理解的可以去学习一下addEventListener函数的使用)

 
  1. window.addEventListener('click', function() {

  2. console.log('4. You click window');

  3. }, true);

此时,点击button的效果是这样的。

可以看到,点击事件先被父元素截获了,且该函数只在事件捕获阶段起作用。

处于目标与事件冒泡阶段

事件到了具体元素时,在具体元素上发生,并且被看成冒泡阶段的一部分。随后,冒泡阶段发生,事件开始冒泡。

阻止事件冒泡

事件冒泡过程,是可以被阻止的。防止事件冒泡而带来不必要的错误和困扰。
这个方法就是:stopPropagation()
我们对button的click事件做一些改造。

 
  1. button.addEventListener('click', function(event) {

  2. // event为事件对象

  3. console.log('1. You click Button');

  4. event.stopPropagation();

  5. console.log('Stop Propagation!');

  6. }, false);

点击后,效果如下图:

不难看出,事件在到达具体元素后,停止了冒泡。但不影响父元素的事件捕获,说明捕获发生在冒泡之前;

总结与感想

事件流:描述的就是从页面中接受事件的顺序。DOM事件流的三个阶段:

  1. 事件捕获阶段----------》2。处于目标阶段----------》3.事件冒泡阶段     

    在这个过程中可以使用event.stopPropagation();来阻止这个过程继续执行;

     

  2. 而addEventListener()的第三个参数为:
  3. true则表示将事件绑定在捕获阶段,false表示将事件绑定在冒泡阶段;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值