DOM事件模型

487 阅读3分钟

了解捕获与冒泡

通过一个例子更好的了解吧

  • 代码-HTML image.png
  • 即.爷爷>.爸爸>.儿子
  • 给三个div分别添加事件监听 fnYe / fnBa / fnEr 点击谁监听谁
  • 针对上面代码提问:
  1. 1点击了谁? 点击文字,算不算点击儿子?

点击文字,算不算点击爸爸?

点击文字,算不算点击爷爷?

-答案:都算

  1. 2. 调用顺序是怎样的?

点击文字,最先调用fnYe /fnBa / fnEr中的哪一个函数?

-答案:都行,看浏览器怎么实现的。

IE5认为先调 fnEr,网景认为先调fnYe,然后掐上了,最后闹到了W3C

和事佬W3C

2002年,W3C发布标准 文档名为DOM Level 2 Events Specification

规定浏览器应该同时支持两种调用顺序

首先按爷爷=>爸爸=>儿子顺序看有没有函数监听

然后按儿子=>爸爸=>爷爷顺序看有没有函数监听

有监听函数就调用,并提供事件信息,没有就跳过

  • 术语: 从外向内找监听函数,叫做事件捕捉;

从内向外找监听函数,叫做事件冒泡;

  • 捕获:当用户点击按钮,浏览器会从 window 从上向下遍历至用户点击的按钮,逐个触发事件处理函数。

  • 冒泡:浏览器从用户点击的按钮从下往上遍历至 window,逐个触发事件处理函数。

  • W3C 事件模型/事件机制:对每个事件先捕获再冒泡

  • DOM事件机制图示: image.png

W3C事件模型

  • 事件绑定API IE 5*: baba.attachEvent(‘onclick’, fn) //冒泡

网景: baba.addEventListener( ‘click’, fn) //捕获

W3C: baba.addEventListener(‘click’, fn, bool)

  • 如果bool不传,或为falsy 就让fn为冒泡,即当浏览器在冒泡阶段发现baba有fn 监听函数,就会调用fn,并提供事件信息;
  • 如果bool为true 就让fn为捕获,即当浏览器在捕获阶段发现 baba有fn 监听函数,就会调用fn ,并提供事件信息;
  • 你可以选择把fn放在哪边 image.png
  • 代码示例: image.png
  • 简化后的代码:js.jirengu.com/luyetuxaba/…
  • 代码图解:

image.png

小结

有两个疑问:

  1. 儿子被点击了,算不算点击爸爸? 算。

  2. 那么先调用爸爸的函数还是先调用儿子的函数?

不确定:IE先调用儿子,firefox就先调用爸爸,最终W3C说我两个都支持,先从老子到儿子,再从儿子到老子,这下你们满意了吧。

捕获与冒泡

捕获说先调用爸爸的监听函数,再调用儿子的监听函数;

冒泡说先调用儿子的监听函数,再调用爸爸的监听函数;

W3C事件模型

先捕获(先爸爸=>儿子) 再冒泡?(再儿子=>爸爸)(可以阻止冒泡)

注意 e 对象被传给所有监听函数

事件结束后, e 对象就不存在了 image.png

一个特例

  • 背景 只有一个div被监听(不考虑父子同时被监听)

fn 分别在捕获阶段和冒泡阶段监听click事件

用户点击的元素就是开发者监听的

  • 代码 image.png
  • 请问: f1先执行还是f2先执行?

如果把两行调换位置后,请问哪个先执行?

错误答案:f2先执行

正确答案:谁先监听谁先执行,没有父子

总结:这是一个特例

取消冒泡

  • 捕获不可取消,但冒泡可以 e.stopPropagation()可中断冒泡,浏览器不再向上走;

通俗来说:有人打我,我自己解决,别告诉我爸爸,一般用于封装某些独立的组件;

  • 所有冒泡皆可取消,默认动作有的可以取消有的不能取消 MDN搜索scroll event,看到Bubbles和 Cancelable

Bubbles的意思是该事件是否冒泡,所有冒泡都可取消

Cancelable 是用来取消(也可以说阻止)默认动作的

Cancelable与冒泡无关

推荐看MDN英文版,中文版内容不全