《DOM 事件模型》

185 阅读2分钟

有如下代码:

<div class="爷爷">
        <div class="爸爸">
            <div class="儿子">文字</div>
        </div>
</div>

给3个div分别添加事件监听fnYe/fnBa/fnEr

现在有3个问题:

点击文字,算不算点击儿子。
点击文字,算不算点击爸爸。
点击文字,算不算点击爷爷。

答:都算

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

答:都行,IE5调用顺序为fnEr->fnBa->fnYe,网景浏览器(远古浏览器)的调用顺序为fnYe->fnBa->fnEr

为了统一标准,W3C在2002年发布了新标准, 文件名为DOM Level 2 Events Specification,规定浏览器同时支持两种调用顺序.首先按爷爷->爸爸->儿子顺序看有没有函数监听,然后按儿子->爸爸->爷爷顺序看有没有函数监听。

用专业术语来说这2种顺序分别就是DOM事件模型的事件捕获和事件冒泡,一个事件发生后,会在子元素和父元素之间传播(propagation)。
由外向内找监听函数, 叫事件监听。
由内向外找监听函数, 叫事件冒泡。

其中div(儿子)就是事件监听和事件冒泡的目标。因此DOM事件模型分为3个阶段: 

(1)捕获阶段:事件从window对象自上而下向目标节点传播的阶段(即: 爷爷->爸爸->儿子); 

(2)目标阶段:真正的目标节点正在处理事件的阶段;(示例代码中: 文字) 

(3)冒泡阶段:事件从目标节点自下而上向window对象传播的阶段(即: 儿子->爸爸->爷爷)。

完整DOM事件模型示意图:


事件绑定api:

IE5*: baba.attachEvent('onclick', fn)//事件冒泡 

网景: baba.addEventListener('click', fn)//事件捕获 

W3C: baba.addEventListener('click', fn, bool), 如果bool不传或为falsy, 则fn使用事件冒泡,反之则fn使用事件捕获.。

你可以选择把fn放在哪边: