Skip to content

DOM的事件模型 #22

@coconilu

Description

@coconilu

1. 事件等级

0级DOM:

从技术上来说,W3C的DOM标准并不支持上述最原始的添加事件监听函数的方式,这些都是在DOM标准形成前的事件模型。尽管没有正式的W3C标准,但这种事件模型仍然得到广泛应用,这就是我们通常所说的0级DOM。 有下面的缺点:

  1. 没有event对象
  2. 事件都是通过标签的attribute来注册的
  3. 所以也可以通过JS操作attribute来注册事件

2级DOM:

DOM级别1于1998年10月1日成为W3C推荐标准。1级DOM标准中并没有定义事件相关的内容,所以没有所谓的1级DOM事件模型。在2级DOM中除了定义了一些DOM相关的操作之外还定义了一个事件模型 ,这个标准下的事件模型就是我们所说的2级DOM事件模型。有如下特性:

  1. 规定事件流分为:1. 事件捕获;2. 目标阶段;3. 事件冒泡
  2. 有event对象,且非IE的回调函数第一个参数都是event对象
  3. 不同的JS引擎会实现自己的事件监听器系统(观察者模式)

2. 相关的类有:

  1. EventTarget,充当事件处理器的容器
  2. Event及其子类,充当事件容器,会在事件流中被传递

3. 事件流:

分为三个阶段:

  1. 事件捕获阶段
  2. 处于目标阶段
  3. 事件冒泡阶段
    我们可以把事件处理器注册在捕获阶段或者冒泡阶段(默认)。
    如下图:
    image

4. 浏览器处理事件流程:

每当一个事件发生时(比如点击事件),浏览器会生成一个事件对象(比如MouseEvent,它集成自UIEvent、Event),根据DOM树结构,找到流传到目标节点的所有父节点。然后进入事件流:
捕获阶段:把事件对象依次传递给各个父节点和自身节点(从上至下),并把注册在捕获阶段的所有事件处理器放到异步处理模块中处理。
冒泡阶段:把事件对象传递给自身节点和各个父节点(从下至上),并把注册在冒泡阶段的所有事件处理器放到异步处理模块中处理。

5. 事件的生命周期:

  1. 事件处理器注册阶段
每个DOM节点都实现了EventTarget的接口,都可以注册事件处理器。
  1. 事件触发阶段(不停地循环)
第一个阶段可以注册的事件的名称是不受限制的,比如你可以注册很多奇形怪状的事件的处理器。
但是,在触发阶段,浏览器只会生成规范的事件对象(比如`click`),也就是说,你注册的除了`click`事件处理器外,都不会被触发。
但是,这并没有阻止我们自己可以触发自己的事件,受限制的只是我们的想象力。

6. EventTarget的接口,详情请参考

addEventListener/attachEvent,注册事件处理器

语法:

target.addEventListener(type, listener[, options]);
target.addEventListener(type, listener ,{capture: Boolean, passive: Boolean, once: Boolean});
target.addEventListener(type, listener[, useCapture]);

参数:

options(默认值都为 false):
一个指定有关 listener 属性的可选参数对象。可用的选项如下:
capture:  Boolean,表示 listener 会在该类型的事件捕获阶段传播到该 EventTarget 时触发。
once:  Boolean,表示 listener 在添加之后最多只调用一次。如果是 true, listener 会在其被调用之后自动移除。
passive: Boolean,设置为true表示 listener 永远不会调用 preventDefault(),如果 listener 仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告。

useCapture:
Boolean,是指在DOM树中,注册了该listener的元素,是否会先于它下方的任何事件目标,接收到该事件。如果没有指定,useCapture 默认为 false 。 

返回值:
undefined

removeEventListener/detachEvent,注销事件处理器

语法:

target.removeEventListener(type, listener[, options]);
target.removeEventListener(type, listener[, useCapture]);

参数:

type
一个字符串,表示需要移除的事件类型,如 "click"。
listener
需要移除的 EventListener 函数(先前使用 addEventListener 方法定义的)。
options 可选
一个可选择的对象:指定有关事件侦听器的特征。可选项有:

- capture : 一个 Boolean 表示这个类型的事件将会被派遣到已经注册的侦听器,然后再派遣到DOM树中它下面的任何 EventTarget。
-  mozSystemGroup: 仅可运行于 XBL 或者 Firefox Chrome,它是一个 Boolean,用于定义是否将侦听器添加到系统组。

useCapture 可选
指定需要移除的 EventListener 函数是否为事件捕获。如果无此参数,默认值为 false。

返回值:
undefined

dispatchEvent/fireEvent,触发事件处理器

语法:

cancelled = !target.dispatchEvent(event)

参数:

event 是要被派发的事件对象。
target 被用来初始化 事件 和 决定将会触发 目标。

返回值:
当该事件是可取消的(cancleable为true)并且至少一个该事件的 事件处理方法 调用了Event.preventDefault(),则返回值为false;否则返回true。

7. Event对象,详情请参考

创建事件:

var event = document.createEvent(type);

方法:

1. preventDefault,阻止执行默认行为,但是事件还是会继续传播
2. stopImmediatePropagation,阻止本节点中剩下的本类型事件处理器执行
3. stopPropagation,阻止事件流继续传播(不论是在捕获还是冒泡阶段)

属性:

bubbles,表示该事件是否在DOM中冒泡。
cancelable,表示这个事件是否可以取消。
cancelBubble,通过在一个事件处理程序返回前设置这个属性的值为真,来阻止事件冒泡。
composed,表示这个事件是否可以在阴影DOM和常规DOM之间的边界上浮动。
currentTarget,当前注册事件的对象的引用。这个值会在传递的途中进行改变。
defaultPrevented,表示了是否已经执行过了event.preventDefault()。
eventPhase,指示事件流正在处理哪个阶段。0: Event.NONE;1: Event.CAPTURING_PHASE,2: Event.AT_TARGET,3: Event.BUBBLING_PHASE。
isTrusted,指明事件是否是由浏览器(当用户点击实例后)——true或者由脚本(使用事件的创建方法,例如event.initEvent)启动——false。
srcElement,target的别名。
target,对事件起源目标的引用。
timeStamp,事件创建时的时间戳,毫秒级别。
type,事件的类型(不区分大小写)。

8. 事件类型

事件类型是事件模型中的重点,但是内容很多,请参考
记录一些常见的事件:

  1. 资源事件,load、DOMContentLoaded(HTML文档完全加载和解析完成之后触发)、abort、error
  2. 网络事件,online、offline
  3. 焦点事件,focus、blur
  4. Websocket事件,open、message、error、close
  5. 会话历史事件
  6. CSS动画事件,animationstart、animationend、animationiteration
  7. 表单事件,reset、submit
  8. 打印事件
  9. 文本组合事件
  10. 视图事件,fullscreenchange、fullscreenerror、resize、scroll
  11. 剪贴板事件,cut、copy、paste
  12. 键盘事件,keydown、keypress、keyup
  13. 鼠标事件,mouseenter、mousemove、mouseout、mousedown、mouseup、click、dbclick、wheel
  14. 拖放事件,dragstart、drag、dragend、dragenter、dragover、dragleave、drop
  15. 媒体事件
  16. 进度事件

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions