#每日一记#通过 GIF 理解 addEventListener、捕获和冒泡

《#每日一记#通过 GIF 理解 addEventListener、捕获和冒泡》 每日一记 – 但并不日更

回想起自己学习事件模式那会儿,怎么都记不住事件的传播流程和 addEventListener 的设置细节,后来发现好的图片更能能帮助我们理解逻,所以做了一个 GIF。

事件传播模式

假设我们现在有三个DOM节点,并且假设 div 为根节点。(通常事件的捕获会从根节点开始)

《#每日一记#通过 GIF 理解 addEventListener、捕获和冒泡》 div -> p -> span

然后我们为这些DOM节点设置好监听。

// 设置第三个参数为 true 则在捕获阶段触发
div.addEventListener('click', null, true);
p.addEventListener('click', null, true);
span.addEventListener('click', null, true);

span.addEventListener('click', null);
p.addEventListener('click', null);
div.addEventListener('click', null);

现在我们点击span,那么click事件会被触发,事件会从div进入捕获阶段,从父级向子级传递,到达事件目标后进入冒泡阶段,从子级像父级传递。

(click)span
=> div -> p -> span -> span -> p -> div

《#每日一记#通过 GIF 理解 addEventListener、捕获和冒泡》 普通流程

如果我们点击p,那么事件目标为p元素,事件从div元素开始捕获,并从p元素处折返变为冒泡。

(click)p
=> div -> p -> p -> div

《#每日一记#通过 GIF 理解 addEventListener、捕获和冒泡》 普通流程

多次绑定

如果在一个节点上多次绑定同一个事件的监听,它们会按照事件传播流程进行(先捕获后冒泡),如果所处流程一样则按照先绑定先触发的原则。

// 设置第三个参数为 true 则在捕获阶段触发
div.addEventListener('click', null, true) // #1
div.addEventListener('click', null)       // #2
div.addEventListener('click', null, true) // #3

p.addEventListener('click', null, true);
p.addEventListener('click', null);

(click)p
=> div#1 -> div#3 -> p -> p -> div#2

《#每日一记#通过 GIF 理解 addEventListener、捕获和冒泡》 多次绑定

虽然申明的顺序是div#1 div#2 div#3,但是捕获先于冒泡,所以 div#1 div#3依次触发,而div#2在冒泡过程中触发。

stopPropagation

这是Event对象的一个方法,用来阻止事件进一步传播。

// 设置第三个参数为 true 则在捕获阶段触发
// #1
div.addEventListener('click', function (event) {
  event.stopPropagation();
}, true) 
div.addEventListener('click', null)       // #2
div.addEventListener('click', null, true) // #3

p.addEventListener('click', null, true);
p.addEventListener('click', null);

(click)p
=> div#1 -> div#3

《#每日一记#通过 GIF 理解 addEventListener、捕获和冒泡》 stopPropagation

使用了stopPropagation()之后,事件就不能进一步传播了,即使是在div上,捕获和冒泡被认为是两个步骤,所以在捕获阶段传播被阻止时同节点上的冒泡也不会触发。

stopImmediatePropagation

这是Event对象的一个方法,一旦调用这个方法,则该元素上未触发的监听都不会被触发,事件也不会进一步传播。

现在我们在div上再多增加一个事件监听,并把stopImmediatePropagation添加在捕获事件中第二个触发的监听上。

// 设置第三个参数为 true 则在捕获阶段触发
div.addEventListener('click', null, true) // #1
div.addEventListener('click', null)       // #2
// #3
div.addEventListener('click', function (e) {
  e. stopImmediatePropagation();
}, true)
div.addEventListener('click', null, true) // #4

p.addEventListener('click', null, true);
p.addEventListener('click', null);

(click)p
=> div#1 -> div#3

《#每日一记#通过 GIF 理解 addEventListener、捕获和冒泡》 stopImmediatePropagation

使用了stopImmediatePropagation()之后,连当前节点中等待触发的监听都沉默了。

扩展阅读

在比较新的浏览器中,addEventListener支持更多参数配置,第三个参数类型支持object

target.addEventListener(type, listener[, options]);

这个 options 支持三个字段

  • capture Boolean 是否在捕获模式触发
  • once Boolean 是否仅触发一次
  • passive Boolean 是否使用被动模式

这里展示一下once的效果

// 设置第三个参数为 true 则在捕获阶段触发
div.addEventListener('click', null, true);
p.addEventListener('click', null, true);
span.addEventListener('click', null, true);

span.addEventListener('click', null);
p.addEventListener('click', null, {once: true}); // 在冒泡阶段只触发一次
div.addEventListener('click', null);

(click)span
=> div -> p -> span -> span -> p -> div

(click)span
=> div -> p -> span -> span -> div

《#每日一记#通过 GIF 理解 addEventListener、捕获和冒泡》 once

Demo

JSbin

罗小黑写写文字

如果喜欢文章 请留下一个赞~
如果喜欢文章 分享给更多人~

掘金中关注我
简书中关注我

自由转载-非商用-非衍生-保持署名(创意共享3.0许可证
转载时请保留原文链接 以保证可及时获取对文章的订正和修改

    原文作者:罗小黑写写文字
    原文地址: https://www.jianshu.com/p/c89e05d77329
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞