JavaScript 事件

本文是我重温 js《高级》书后整理的笔记。

所谓事件,就是文档或者浏览器窗口发生的一些特定的交互瞬间。

事件流

定义

页面中接收事件的顺序

类别

  • 事件捕获 (Netscape)
  • 事件冒泡 (IE)

曾经有个前辈问我,事件捕获和事件冒泡哪个比较重要。

那时候,我答不上来。

答案他没有说。

我现在知道,是事件冒泡。

(下文会给出解释)

事件冒泡

顺序

最具体的元素 ==> 文档(也就是 document)

注意

IE9+、FF、Chrome、Safari 中会一直冒泡到 window 对象

事件捕获

顺序

和冒泡相反。

window ==> 最具体元素

DOM 事件流

DOM 事件流在 DOM2 级事件里规定,并且 IE8- 的浏览器不支持。

阶段

它规定了事件流应该包括三个阶段

事件捕获 => 处于目标阶段 => 事件冒泡

注意

  • 事件捕获阶段,在元素的父级元素就已经停止。这个阶段中,目标元素不会接收到事件。

  • 处于目标的阶段,通常会视为冒泡的一部分,事件从这个地方开始,往上冒泡传递回文档。

事件处理程序

顾名思义,某个事件发生时响应的一段程序(函数)。

它的制定经过了几个阶段:

  1. HTML 事件处理程序
  2. DOM0 级事件处理程序
  3. DOM2 级事件处理程序
  4. DOM3 级事件处理程序

(不要问我为什么没有 DOM1)

下面将它简称为 handler。

DOM0 级

把函数赋给 DOM 元素的一个事件属性

var btn = document.getElementById('btn');
btn.onclick = function() {
// to-do
}

执行时机

在冒泡阶段执行。

删除

把该属性的值赋为 null

DOM2 级

可以为一个元素的同一事件添加多个处理程序。

操作

  • 添加事件 - addEventListener()
  • 删除事件 - removeEventListener()

两个方法的参数一致:

  • 事件类型
  • 事件处理程序
  • 布尔值(是否在捕获阶段处理事件)(一般以及默认都是 false,不使用捕获,使用冒泡)

特点

绑定了多个 handler 时,事件触发它们的执行顺序为先到先执行(队列)

注意

第二个参数为匿名函数的话,如果没有保存其引用,将无法清除该 handler

且 IE8- 的浏览器不支持 DOM2 级事件处理程序,自己有一套机制(下讲)。

p.s.

还记得一开始的问题吗——“事件捕获和事件冒泡哪个重要”。

在 DOM0 级~中,handler 执行时机是在冒泡阶段;
在 DOM2 级~,我们注册 handler 时,默认使用事件冒泡,也就是说,一般我们不用捕获。

综上两点,可以看出,冒泡比捕获重要些。

IE 事件处理程序

上面讲到,IE8- 的浏览器不支持 DOM2 级,但它们自己有一套事件处理机制。

同样,是通过元素的方法来实现绑定。

操作

  • 添加事件 - attachEvent()
  • 删除事件 - detachEvent()

两个方法都只接受两个参数。

参数 形式
事件类型 ‘on’ + type
处理程序 handler

特点

  1. 只在冒泡阶段执行
  2. handler 的作用域为 window
  3. 绑定多个 handler 时,执行顺序为后来居上(栈)

事件对象(非IE8-)

就是 event 对象。包含着所有与事件有关的信息。

特别的属性和方法

属性名 意义
currentTarget 事件注册的元素
target 事件的目标
preventDefault() 只能取消 cancelable 为 true 的事件的默认行为
eventPhase 可以确定事件当前位于事件流的哪个阶段

特点

在 handler 可以获得

事件对象(IE8-)

访问方式

  • 使用 DOM0 级方式的话,就通过 window.event 来获得

  • 使用 IE 事件处理程序时,会往 handler 传入 event 参数;但也可以使用 window.event

特别的属性和方法

属性名 意义
srcElement 等同 DOM 的 target 属性
cancelBubble 设置为 true 就可取消冒泡
returnValue 设置为 false 时等同 preventDefault()