本文你将看到
- DOM事件模型到底解决了什么问题
- 什么是捕获,什么是冒泡
- 捕获和冒泡可以取消吗
一、什么是DOM事件模型
- 先来看这样一段代码:
<div class='grandpa'>
<div class='dad'>
<div class='son'>
内容
</div>
</div>
</div>
给三个div grandpa/dad/son分别监听点击事件函数 fnGrandpa/fnDad/fnSon,那么请问:
- 用户点击“内容”,算点击了
爷爷还是爸爸还是儿子? - 用户点击“内容”,先调用
fnGrandpa/fnDad/fnSon中哪一个函数?
答案模棱两可:都对,都行。
- 和事佬W3C立了规矩 为了解决上文两个问题,W3C在2002年发布了标准文档,做了如下规定:
- 浏览器应当同时支持两种调用顺序
- 先按照从外到里(爷爷>爸爸>儿子)的顺序看有没有函数监听,再按照从里到外(儿子>爸爸>爷爷)的顺序看有没有事件监听
- 有监听函数就调用,并提供事件信息,没有就跳过
这就是DOM事件的来源
二、什么是捕获,什么是冒泡?
先按照从外到里(爷爷>爸爸>儿子)的顺序看有没有函数监听,再按照从里到外(儿子>爸爸>爷爷)的顺序看有没有事件监听
上文提到的这条规定中,从外到内找监听函数,就叫事件捕获,从内到外找监听函数,就叫事件冒泡,浏览器默认先捕获,后冒泡
- 完整的DOM事件模型分为三个阶段:
- 捕获阶段 Capture phase
- 目标阶段 Target Phase
- 冒泡阶段 Bubbling Phase
其中目标阶段,是指真正的目标节点正在处理事件的阶段,如用户点击上文代码中的“内容”
- 我们可以选择监听函数放在捕获阶段还是冒泡阶段
- 事件绑定API
// IE5 dad.attachEvent('onclick',fn) // 冒泡 // 网景 dad.addEventListner('click',fn) // 捕获 // W3C用法 dad.addEventListener('click', fn, bool)- 当
bool不传参或为falsy,fn放在冒泡阶段 - 当
bool为true时,fn放在捕获阶段
三、捕获和冒泡可以取消吗
- 捕获不能取消,但冒泡可以
- 可以用
e.stopPropagation()中断冒泡
- 可以用
- 不可阻止默认动作
- 如滚动事件 scroll event 有两个属性
Bubbles指该事件是否冒泡Cancelable指开发者是否可以阻止默认事件
- 如滚动事件 scroll event 有两个属性
- 所有冒泡都可取消
- Cancelale 与冒泡无关