JS的事件冒泡和捕获

天时地利的迷信~


各位宝宝,最近怎么样?北京的冬天来了,好冷,幸好下了一场不大不小的雪,否则对冬天真是喜欢不起来。

事件机制


事件触发三个阶段:

  • window往事件触发处传播,遇到注册的捕获事件会触发
  • 传播到事件触发处时触发注册的事件
  • 从事件触发处往window传播,遇到注册的冒泡事件会触发

事件触发一般会按照?的顺序进行(W3C模型)

         1. 先从上往下捕获                    |                   | |  / \ ------------------| |--| |-----------------|   outer         | |  | |                ||    -------------| |--| |-----------     ||    |   inner     \ /  | |           |    ||   |                   |            |    ||    |  2. 到达目标元素后从下往上冒泡     |    ||    --------------------------------      ||        W3C event model                   |-------------------------------------------

但是有一个特例:如果给body中的子节点同时注册冒泡和捕获事件,事件触发会按照注册的顺序执行。

// 以下会先打印冒泡然后是捕获node.addEventListener(  'click',  event => {    console.log('冒泡')  },  false)node.addEventListener(  'click',  event => {    console.log('捕获 ')  },  true)

我们来看一下如下代码到底是怎么的结果:

var selector = document.querySelector.bind(document);selector('div.outer').addEventListener('click', (e) => {    selector('p:first-of-type').textContent += 'outer clicked! '}, true)selector('div.inner').addEventListener('click', (e) => {    selector('p:first-of-type').textContent += 'inner clicked! '}, false)document.addEventListener('click', (e) => {    selector('p:first-of-type').textContent += 'document clicked! '}, true)

当点击innner元素时,如下元素发生了:

  1. 点击事件开始于捕获阶段,在此阶段浏览器会在所有祖先元素上查找点击事件处理函数(从document开始)
  2. 结果找到了2个,分别在document和outer上面,而且这两个事件处理函数的useCapture选项为true,说明他们被注册在捕获阶段的。于是,document和outer的点击处理函数被执行
  3. 继续向下寻找,直到到达inner元素本身,捕获阶段就此结束。此时进入冒泡阶段,inner上的时间处理器得到执行
  4. 事件命中元素后开始向上冒泡,一路查找是否注册了冒泡阶段的祖先元素上的时间处理器。由于没有找到因此什么也没发生。

最后的结果是

// logdocument clicked! outer clicked! inner clicked!

我们把时间注册在冒泡阶段(addEventListener的useCapture选项为false)

var selector = document.querySelector.bind(document);selector('div.outer').addEventListener('click', (e) => {    selector('p:first-of-type').textContent += 'outer clicked! '    console.log(e);}, false)selector('div.inner').addEventListener('click', (e) => {    selector('p:first-of-type').textContent += 'inner clicked! '    console.log(e);}, false)document.addEventListener('click', (e) => {    selector('p:first-of-type').textContent += 'document clicked! '}, false)

结果是:

// loginner clicked! outer clicked! document clicked!

愿我们有能力不向生活缴械投降---Lin

本文分享自微信公众号 - 女程序员的日常(gh_df41d619fb70)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-12-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励