DOM 事件模型或 (DOM 事件机制)

92 阅读2分钟

DOM 的事件操作(监听和触发),都定义在EventTarget接口。 接口主要提供三个实例方法。

  • addEventListener:绑定事件的监听函数
  • removeEventListener:移除事件的监听函数
  • dispatchEvent:触发事件

一个事件发生后,会在子元素及父元素之间进行传播(propagation),这种传播分为三个阶段。(这种三阶段的传播模型,使得同一个事件会在多个节点上触发。)

  1. 由外向内找监听函数就是事件捕获
  2. 在目标节点触发事件
  3. 由内而外找监听函数就是事件冒泡

事件传播的最上层对象是window,上例的事件传播顺序,在捕获阶段依次为window、document、html、body、父节点、目标节点,在冒泡阶段依次为目标节点、父节点、body、html、document、window。

DOM事件传播的三个阶段:捕获阶段目标阶段冒泡阶段

此处以点击事件为例

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

即 .爷爷>.爸爸>.儿子 给三个div分别添加事件监听 fnYe / fnBa / fnEr ,点击‘文字’后,调用顺序是怎样的?

IE 5*:baba.attachEvent('onclick', fn) // 冒泡
网景:baba.addEventListener('click',fn) // 捕获
W3C:baba.addEventListener('click', fn, bool)  // bool===空/falsy,冒泡 ; bool===true,捕获

W3C制定了标准
首先 按爷爷=>爸爸=>儿子顺序看有没有函数监听
然后 按儿子=>爸爸=>爷爷顺序看有没有函数监听
有监听函数就调用,并提供事件信息,没有就跳过

从外向内找监听函数,叫事件捕获
从内向外找监听函数,叫事件冒泡
开发者自己选择把 fnYe 放在捕获阶段还是放在冒泡阶段

syt.png

代码示例

代码.png tj.png

W3C 事件模型

先捕获(先爸爸=>儿子)再冒泡(再儿子=>爸爸)
注意 e 对象被传给所有监听函数
事件结束后,e 对象就不存在了

注意

div > span{文字},用户点击文字
e.target 就是 span , e.target就是被用户操作的元素
e.currentTarget (this) 就是 div , e.currentTarget就是被监听的元素

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

特例

只有一个 div 被监听(不考虑父子同时被监听),fn 分别在捕获阶段和冒泡阶段监听 , click 事件 用户点击的元素就是开发者监听的
div.addEventLisenter('click', f1)
div.addEventLisenter('click', f2, true)
先执行f1还是f2 ?
答案:谁先监听谁先执行。因为他们是同辈。