JavaScript 中的事件模型有哪些

JavaScript 中的事件模型有哪些

事件模型
事件与事件流
原始事件模型
标准事件模型
IE 事件模型

一、事件与事件流

JavaScript 中的事件,可以理解就是在 HTML 文档或者浏览器中发生的一种交互操作,使得网页具备互动性,常见的有加载事件、鼠标事件、自定义事件等。

由于 DOM 是一个树结构,如果在父子节点绑定事件时候,当触发子结点的时候,就存在一个顺序问题,这就涉及到了事件流的概念。

事件流都会经历三个阶段:

  • 事件捕获阶段(capture phase)
  • 处于目标阶段(target phase)
  • 事件冒泡阶段(bubbling phase)

事件冒泡与事件捕获

<div id="outer">
  <p id="inner">Click me!</p>
</div>

事件冒泡是一种从下往上的传播方式,由最具体的元素(触发节点)然后逐渐向上传播到最不具体的那个节点,也就是 DOM 中最高层的父节点。

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

因此在事件冒泡的概念下在 p 元素上发生 click 事件的顺序应该是 p -> div -> body -> html -> document

网景提出另一种事件流名为事件捕获(event capturing)。与事件冒泡相反,事件最开始由不太具体的节点最早接受事件,而最具体的节点(触发节点)最后接受事件。

因此,在事件捕获的概念下,在 p 元素上发生 click 事件的顺序应该是 document -> html -> body -> div -> p

网景和微软曾经的战争还是比较火热的,当时,网景主张捕获方式,微软主张冒泡方式。后来 w3c 采用折中的方式,平息了战火,指定了统一的标准——先捕获再冒泡

二、事件模型

事件模型可以分为三种:

  • 原始事件模型(DOM0 级)
  • 标准事件模型(DOM2 级)
  • IE 事件模型(基本不用)

原始事件模型

事件绑定监听函数比较简单,有两种方式:

  • HTML 代码中直接绑定
<input type="button" onclick="fun()" />
  • 通过 JS 代码绑定
var btn = document.getElementById('btn')
btn.onclick = fun

特性

  • 绑定速度快

    DOM0级事件具有很好的跨浏览器优势,会以最快的速度绑定,但由于绑定速度太快,可能页面还未完全加载出来,以至于事件可能无法正常运行

  • 只支持冒泡,不支持捕获

  • 同一个类型的时间只能绑定一次

<input type="button" id="btn" onclick="fun1()">

var btn = document.getElementById('btn')
btn.onclick = fun2

如上,当希望为同一个元素绑定多个同类型事件的时候(上面的这个 btn 元素绑定 2 个点击事件),是不被允许的,后绑定的事件会覆盖之前的事件。

删除 DOM0 级事件处理程序只要将对应事件属性置为 null 即可。

btn.onclick = null

标准事件模型

在该事件模型中,一次事件共有三个过程:

  • 事件捕获阶段:事件从 document 一直向下传播到目标元素,依次检查经过的节点是否绑定了事件监听函数,如果有则执行。
  • 事件处理阶段:事件到达目标元素,触发目标元素的监听函数。
  • 事件冒泡阶段:事件从目标元素冒泡到 document,依次检查经过的节点是否绑定了事件监听函数,如果有则执行。

事件绑定监听函数的方式如下:

element.addEventListener(eventType, handler, useCapture)

事件移除监听函数的方式如下:

element.removeEventListener(eventType, handler, useCapture)

参数如下:

  • eventType 指定事件类型(不要加 on)。
  • handler 是事件处理函数。
  • useCapture 是一个 boolean 用于指定是否在捕获阶段进行处理,一般设置为 false 与 IE 浏览器保持一致。

举个例子:

var btn = document.getElementById('btn')
btn.addEventListener('click', showMessage, false)
btn.removeEventListener('click', showMessage, false)

特性

  • 可以在一个 DOM 元素上绑定多个事件处理器,各自并不会冲突
btn.addEventListener('click', showMessage1, false)
btn.addEventListener('click', showMessage2, false)
btn.addEventListener('click', showMessage3, false)
  • 执行时机

    当第三个参数(useCapture)设置为 true 就在捕获过程中执行,反之在冒泡过程中执行处理函数。

下面举个例子

<div id="div">
  <p id="p">
    <span id="span">Click Me~</span>
  </p>
</div>

设置点击事件

var div = document.getElementById('div')
var p = document.getElementById('p')

function onClickFn(event) {
  var tagName = event.currentTarget.tagName
  var phase = event.eventPhase
  console.log(tagName, phase)
}

div.addEventListener('click', onClickFn, false)
p.addEventListener('click', onClickFn, false)

上述使用了 eventPhase,返回了一个代表当前执行阶段的整数值。1 为捕获阶段,2 为事件对象触发阶段,3 为冒泡阶段。

点击 Click Me~,输出如下:

P 3
DIV 3

可以看到,pdiv 都是在冒泡阶段响应了事件,由于冒泡的特性,裹在里层的 p 率先做出响应。

如果把第三个参数都改为 true

div.addEventListener('click', onClickFn, true)
p.addEventListener('click', onClickFn, true)

输出如下:

DIV 1
P 1

两者都是在捕获阶段响应事件,所以 divp 标签先做出响应。

IE 事件模型

IE 事件模型共有两个过程:

  • 事件处理阶段:事件到达目标元素,触发目标元素的监听函数。
  • 事件冒泡阶段:事件从目标元素冒泡到 document,依次检查经过的节点是否绑定了事件监听函数,如果有则执行。

事件绑定监听函数的方式如下:

attachEvent(eventType, handler)

事件移除监听函数的方式如下:

detachEvent(eventType, handler)

举个例子

var btn = document.getElementById('btn')
btn.attachEvent('onclick', showMessage)
btn.detachEvent('onclick', showMessage)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值