简述DOM事件机制

134 阅读2分钟
<div class='爷爷'>
    <div class='爸爸'>
        <div class='儿子'>
            文字
        </div>
    </div>
</div>

假设已经给三个 div 分别添加了事件监听 fnYe / fnBa / fnEr

什么是捕获

由外向内 找监听函数,叫做事件捕获,即: 爷爷 => 爸爸 => 儿子

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

什么是冒泡

由内向外 找监听函数,叫做事件冒泡,即: 儿子 => 爸爸 => 爷爷

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

先捕获还是先冒泡的问题

  • 事件冒泡 微软提出了名为事件冒泡( event bubbling )的事件流。事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到 document 对象。

IE5 为例,先进行事件捕获捕获:

baba.attachEvent('onclick',fn) //先冒泡
  • 事件捕获 网景提出另一种事件流名为事件捕获( event capturing )。与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。
baba.addEventListener('click',fn) //先捕获
  • W3C制定的规则: 网景主张捕获方式,微软主张冒泡方式。

后来 W3C 采用折中的方式,平息了战火,制定了统一的标准——先捕获再冒泡addEventListener 的第三个参数就是为冒泡和捕获准备的:

element.addEventListener('click', function, bool)

第一个参数是需要绑定的事件

第二个参数是触发事件后要执行的函数

第三个参数为空或者为 falsy 值时,表示在事件冒泡阶段调用事件处理函数;如果参数为 true ,则表示在事件捕获阶段调用处理函数。

  • 存在一个特例 特例

取消冒泡

捕获不能取消,冒泡可以 e.stopPropagation() 中断冒泡

本文参考摘录了:

  1. JS中事件冒泡与捕获
  2. 简述 DOM 事件模型或 DOM 事件机制