带你看懂DOM事件模型(事件机制)

367 阅读2分钟

本文你将看到

  • DOM事件模型到底解决了什么问题
  • 什么是捕获,什么是冒泡
  • 捕获和冒泡可以取消吗

一、什么是DOM事件模型

  • 先来看这样一段代码:
<div class='grandpa'>
    <div class='dad'>
        <div class='son'>
            内容
        </div>
    </div>
</div>

给三个div grandpa/dad/son分别监听点击事件函数 fnGrandpa/fnDad/fnSon,那么请问:

  1. 用户点击“内容”,算点击了爷爷还是爸爸还是儿子
  2. 用户点击“内容”,先调用 fnGrandpa/fnDad/fnSon中哪一个函数?

答案模棱两可:都对,都行。

  • 和事佬W3C立了规矩 为了解决上文两个问题,W3C在2002年发布了标准文档,做了如下规定:
  1. 浏览器应当同时支持两种调用顺序
  2. 先按照从外到里(爷爷>爸爸>儿子)的顺序看有没有函数监听,再按照从里到外(儿子>爸爸>爷爷)的顺序看有没有事件监听
  3. 有监听函数就调用,并提供事件信息,没有就跳过

这就是DOM事件的来源

二、什么是捕获,什么是冒泡?

先按照从外到里(爷爷>爸爸>儿子)的顺序看有没有函数监听,再按照从里到外(儿子>爸爸>爷爷)的顺序看有没有事件监听

上文提到的这条规定中,从外到内找监听函数,就叫事件捕获,从内到外找监听函数,就叫事件冒泡,浏览器默认先捕获,后冒泡

  • 完整的DOM事件模型分为三个阶段:
    • 捕获阶段 Capture phase
    • 目标阶段 Target Phase
    • 冒泡阶段 Bubbling Phase

image.png

其中目标阶段,是指真正的目标节点正在处理事件的阶段,如用户点击上文代码中的“内容”

  • 我们可以选择监听函数放在捕获阶段还是冒泡阶段
    • 事件绑定API
    // IE5
    dad.attachEvent('onclick',fn) // 冒泡
    // 网景
    dad.addEventListner('click',fn) // 捕获
    // W3C用法
    dad.addEventListener('click', fn, bool)
    
    • bool 不传参或为 falsyfn 放在冒泡阶段
    • bool 为true时,fn 放在捕获阶段

image.png

三、捕获和冒泡可以取消吗

  • 捕获不能取消,但冒泡可以
    • 可以用e.stopPropagation()中断冒泡
  • 不可阻止默认动作
    • 如滚动事件 scroll event 有两个属性
      • Bubbles 指该事件是否冒泡
      • Cancelable 指开发者是否可以阻止默认事件

image.png

  • 所有冒泡都可取消
  • Cancelale 与冒泡无关