JS的事件冒泡和捕获

2019-12-04 12:03:47 浏览数 (1)

天时地利的迷信~


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

事件机制


事件触发三个阶段:

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

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

代码语言:javascript复制
         1. 先从上往下捕获                    |                   | |  /  ------------------| |--| |-----------------|   outer         | |  | |                ||    -------------| |--| |-----------     ||    |   inner      /  | |           |    ||   |                   |            |    ||    |  2. 到达目标元素后从下往上冒泡     |    ||    --------------------------------      ||        W3C event model                   |-------------------------------------------

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

代码语言:javascript复制
// 以下会先打印冒泡然后是捕获node.addEventListener(  'click',  event => {    console.log('冒泡')  },  false)node.addEventListener(  'click',  event => {    console.log('捕获 ')  },  true)

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

代码语言:javascript复制
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. 事件命中元素后开始向上冒泡,一路查找是否注册了冒泡阶段的祖先元素上的时间处理器。由于没有找到因此什么也没发生。

最后的结果是

代码语言:javascript复制
// logdocument clicked! outer clicked! inner clicked!

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

代码语言:javascript复制
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)

结果是:

代码语言:javascript复制
// loginner clicked! outer clicked! document clicked!

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

0 人点赞