DOM 事件处理方式演进
DOM0、DOM2、DOM3 三种事件处理方式的区别与用法
问题
介绍 DOM0、DOM2、DOM3 事件处理方式的区别。
解答
DOM0 级事件
通过 HTML 属性或元素属性直接绑定事件处理函数。
<!-- 方式1:HTML 属性 -->
<button onclick="handleClick()">点击</button>
<script>
function handleClick() {
console.log('clicked');
}
</script>
// 方式2:元素属性
const btn = document.getElementById('btn');
btn.onclick = function() {
console.log('clicked');
};
// 同一事件只能绑定一个处理函数,后面的会覆盖前面的
btn.onclick = function() {
console.log('new handler'); // 只有这个会执行
};
// 移除事件
btn.onclick = null;
DOM2 级事件
引入 addEventListener 和 removeEventListener,支持事件捕获和冒泡。
const btn = document.getElementById('btn');
function handler1() {
console.log('handler1');
}
function handler2() {
console.log('handler2');
}
// 可以绑定多个处理函数,按顺序执行
btn.addEventListener('click', handler1, false);
btn.addEventListener('click', handler2, false);
// 第三个参数:false 表示冒泡阶段触发(默认),true 表示捕获阶段触发
btn.addEventListener('click', handler1, true); // 捕获阶段
// 移除事件(必须是同一个函数引用)
btn.removeEventListener('click', handler1, false);
// 事件流演示:捕获 -> 目标 -> 冒泡
document.getElementById('outer').addEventListener('click', () => {
console.log('outer 捕获');
}, true);
document.getElementById('outer').addEventListener('click', () => {
console.log('outer 冒泡');
}, false);
document.getElementById('inner').addEventListener('click', () => {
console.log('inner 捕获');
}, true);
document.getElementById('inner').addEventListener('click', () => {
console.log('inner 冒泡');
}, false);
// 点击 inner 输出顺序:outer 捕获 -> inner 捕获 -> inner 冒泡 -> outer 冒泡
DOM3 级事件
在 DOM2 基础上扩展了更多事件类型,并允许自定义事件。
// DOM3 新增的事件类型
// UI 事件:load、scroll、resize
// 焦点事件:focus、blur、focusin、focusout
// 鼠标事件:click、dblclick、mouseenter、mouseleave
// 键盘事件:keydown、keyup、keypress
// 输入事件:textInput、input
// 合成事件:compositionstart、compositionupdate、compositionend
// 自定义事件
const customEvent = new CustomEvent('myEvent', {
detail: { message: 'Hello' }, // 传递数据
bubbles: true, // 是否冒泡
cancelable: true // 是否可取消
});
const element = document.getElementById('target');
element.addEventListener('myEvent', (e) => {
console.log(e.detail.message); // 'Hello'
});
// 触发自定义事件
element.dispatchEvent(customEvent);
三者对比
| 特性 | DOM0 | DOM2 | DOM3 |
|---|---|---|---|
| 绑定方式 | 属性赋值 | addEventListener | addEventListener |
| 多个处理函数 | ❌ 覆盖 | ✅ 支持 | ✅ 支持 |
| 事件捕获 | ❌ | ✅ | ✅ |
| 移除事件 | 赋值 null | removeEventListener | removeEventListener |
| 自定义事件 | ❌ | ❌ | ✅ |
关键点
- DOM0 通过属性绑定,同一事件只能有一个处理函数
- DOM2 引入
addEventListener,支持多个处理函数和事件捕获/冒泡 - DOM3 扩展了事件类型,支持
CustomEvent自定义事件 - 事件流顺序:捕获阶段 → 目标阶段 → 冒泡阶段
removeEventListener必须传入相同的函数引用才能移除
目录