🍎 JavaScript 事件模型
相关问题:
- JavaScript 中对事件模型的理解。
# 概念:事件与事件流
JavaScript 中的事件,理解为在 HTML 文档或者浏览器中发生的交互操作。常见的事件有 加载事件、鼠标事件、自定义事件。
DOM 是一个树结构,如果父子节点绑定事件时,当触发子节点时,存在事件的顺序问题。这就涉及事件流的概念。
事件流都会经历三个阶段:
- 事件捕获阶段
- 目标阶段
- 冒泡阶段
# 概念:事件模型
事件模型可以分为三种类型:
- 原始事件模型(DOM 0 级)
- 标准事件模型(DOM 2 级)
IE 事件模型(基本不用)
# 原始事件模型
特点:
- 事件绑定速度快;
- 只支持冒泡,不支持捕获;
- 同一类型的事件只能绑定一次;
🌰 例子 / 事件绑定监听函数的方式:
在 HTML 中直接绑定:
<input type="button" onclick="fun()">
1
通过 JavaScript 代码绑定:
var btn = document.getElementById("#btn")
btn.onclick = function() {
...
}
1
2
3
4
2
3
4
🌰 例子 / 同类型的事件只能绑定一次:
<input type="button" id="btn" onclick="fun1()">
1
var btn = document.getElementById('.btn');
btn.onclick = fun2;
1
2
2
这里为
btn
绑定了两个同类型的(点击)事件,后面绑定的事件会覆盖之前的事件。
🌰 例子 / 删除之间绑定的事件:
btn.onclick = null
1
# 标准事件模型
该事件模型中,一次事件共有三个过程:
- 事件捕获阶段:事件从
document
一直向下传播到目标元素,一次检查经过的节点是否绑定了事件监听函数,如果有则执行。 - 事件处理阶段:事件到达目标元素,触发目标元素的监听函数。
- 事件冒泡阶段:事件从目标元素冒泡到
document
,依次检查经过的节点是否绑定了事件监听函数,如果有则执行。
特点:
- 可以在一个 DOM 元素上绑定多个事件处理器,各自不会冲突;
- 执行实时机:当
addEventListener()
第三个参数useCapture
设置为true
就在捕获过程中执行,反之在冒泡过程中执行处理函数;
🌰 例子 / 绑定监听函数和移除监听函数:
addEventListener(eventType, handler, useCapture)
1
removeEventListener(eventType, handler, useCapture)
1
🌰 例子 / 绑定点击事件:
var btn = document.getElementById('.btn');
btn.addEventListener(‘click’, showMessage, false);
btn.removeEventListener(‘click’, showMessage, false);
1
2
3
2
3
绑定多个点击事件:
btn.addEventListener(‘click’, showMessage1, false);
btn.addEventListener(‘click’, showMessage2, false);
btn.addEventListener(‘click’, showMessage3, false);
1
2
3
2
3
🌰 例子 / 设置事件的执行时机:
<div id='div'>
<p id='p'>
<span id='span'>Click Me!</span>
</p >
</div>
1
2
3
4
5
2
3
4
5
设置 useCapture
为 false
:
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);
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
使用了
eventPhase
,返回一个代表当前执行阶段的整数值。1 为捕获阶段、2 为事件对象触发阶段、3 为冒泡阶段。此时,
p
和div
都在冒泡阶段响应了事件,因为冒泡的特性,所以p
率先做出响应。如果把
useCapture
设置为true
,输出的结果应该为:DIV 1 P 1
1
2意味着两者都是在捕获阶段响应事件,所以
div
比p
先做出响应。
编辑 (opens new window)
📢 上次更新: 2022/09/02, 10:18:16