亮神知识库 亮神知识库
首页
  • 手写代码

    • 手写代码系列
  • 基础知识

    • 基础
    • JS底层
    • CSS
  • 原理
  • 浏览器
  • HTTP
  • 网络安全
  • babel
  • webpack基础
  • webpack进阶
  • Vite
  • TypeScript
  • Vue2
  • Vue3
  • Node基础

    • glob
    • 模块化机制
    • 事件循环
    • KOA2框架原理
    • Node子进程
    • cluster原理(了解)
  • 教育行业2021

    • B端
    • C端
    • 工具
  • 游戏行业2025
  • 刷题
  • 杂(待整理)
  • 学习
  • 面试
  • 实用技巧
  • 心情杂货
  • 年度总结
  • 友情链接
关于
  • 分类
  • 标签
  • 归档
  • 收藏
GitHub (opens new window)

亮神

前程明亮,未来可期
首页
  • 手写代码

    • 手写代码系列
  • 基础知识

    • 基础
    • JS底层
    • CSS
  • 原理
  • 浏览器
  • HTTP
  • 网络安全
  • babel
  • webpack基础
  • webpack进阶
  • Vite
  • TypeScript
  • Vue2
  • Vue3
  • Node基础

    • glob
    • 模块化机制
    • 事件循环
    • KOA2框架原理
    • Node子进程
    • cluster原理(了解)
  • 教育行业2021

    • B端
    • C端
    • 工具
  • 游戏行业2025
  • 刷题
  • 杂(待整理)
  • 学习
  • 面试
  • 实用技巧
  • 心情杂货
  • 年度总结
  • 友情链接
关于
  • 分类
  • 标签
  • 归档
  • 收藏
GitHub (opens new window)
  • 浏览器工作原理与实践

  • 浏览器

    • JSONP
    • URL输入到返回请求的过程
    • 浏览器缓存
    • 层合成
    • 事件机制、模型
      • 事件流
        • 事件捕获
        • 事件冒泡
      • 事件处理
        • DOM0 事件处理
        • DOM2 事件处理
      • 事件对象
      • 面试
    • 跨域
  • HTTP

  • 网络安全

  • 浏览器
  • 浏览器
0zcl
2021-06-18
目录

事件机制、模型

# 事件流

# 事件捕获

事件捕获 是 <strong>由外到内的</strong>

capture

# 事件冒泡

事件捕获 是 <strong>由内到外的</strong>

bubble

DOM2 Events 规范规定事件流分为 3 个阶段: <code>事件捕获</code>、<code>到达目标</code> 和 <code>事件冒泡</code> event

# 事件处理

# DOM0 事件处理

  • 事件处理函数中的<code>this</code>指向事件的目标元素
  • 一个元素有多个<code>DOM0</code>事件,则后面的覆盖前面的,最终只执行最后一个<code>DOM0</code>事件
const btn = document.getElementById("zcl");
btn.onclick = function(){
  console.log(this) // this 指向btn
  console.log('Clicked')
}
// 移除事件
btn.onclick = null;
1
2
3
4
5
6
7

# DOM2 事件处理

通过addEventListener (opens new window)、<code>removeEventListener</code>来添加和移除事件。

target.addEventListener(type, listener, options);
target.addEventListener(type, listener, useCapture)
1
2

addEventListener我们是比较熟悉了,之前手写事件委托等早已写过。这里注意 第三个参数 可以是一个 option 对象或一个布尔值<code>useCapture</code>。 useCapture 参数指定了该事件处理程序触发的 “时机” :是在事件流的捕获阶段还是冒泡阶段

  • true:表示在捕获阶段调用事件处理程序
  • false: (默认值)表示在冒泡阶段调用事件处理程序

# 事件对象

  1. event.preventDefault (opens new window): 阻止事件的默认行为. eg: 选中复选框是点击复选框的默认行为
document.querySelector("#id-checkbox").addEventListener("click", function(event) {
  document.getElementById("output-box").innerHTML += "Sorry! <code>preventDefault()</code> won't let you check this!<br>";
  event.preventDefault();
}, false)
1
2
3
4

Please click on the checkbox control.

  1. event.stopPropagation (opens new window): 阻止事件流在 DOM 中的传播,取消后续的事件捕获或冒泡
var div = document.querySelector('#div');
div.addEventListener("click", (e) => {
  console.log("clicked");
  e.stopPropagation()
}, false);
document.body.addEventListener("click", () => {
  console.log("body clicked");
}, false);
// clicked  如果不调用 stopPropagation() 那么点击 div 会有两个 log 记录
1
2
3
4
5
6
7
8
9
  1. event.target & event.currentTarget 手写事件委托中,用的是<code>event.target</code>, 不用event.currentTarget! 看下面就知道为啥了hh
  • event.target: 指向触发事件的元素。event.target是事件的真正发出者
  • event.current: 指向事件绑定的元素。vent.currentTarget始终是监听事件者
<div id="a">
  <div id="b">
    <div id="c">
      <div id="d"></div>
    </div>
  </div>
</div>
<script>
  document.getElementById('a').addEventListener('click', function(e) {
    console.log(
      'target:' + e.target.id + '&currentTarget:' + e.currentTarget.id
    )
  })
  document.getElementById('b').addEventListener('click', function(e) {
    console.log(
      'target:' + e.target.id + '&currentTarget:' + e.currentTarget.id
    )
  })
  document.getElementById('c').addEventListener('click', function(e) {
    console.log(
      'target:' + e.target.id + '&currentTarget:' + e.currentTarget.id
    )
  })
  document.getElementById('d').addEventListener('click', function(e) {
    console.log(
      'target:' + e.target.id + '&currentTarget:' + e.currentTarget.id
    )
  })
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

当我们点击最里层的元素d的时候,会依次输出:

target:d&currentTarget:d
target:d&currentTarget:c
target:d&currentTarget:b
target:d&currentTarget:a
1
2
3
4

# 面试

浏览器的事件模型/机制,关键词:<code>事件捕获</code>、<code>事件冒泡</code>、<code>DOM0 事件</code>、<code>DOM2 事件</code>。理解上还是很容易的,下面来做道题

<div>
  <button>123</button>
</div>
btn.addEventListener("click", (e) => {
  console.log('btn click capture ')
}, true);

btn.addEventListener("click", (e) => {
  console.log('btn click bubble ')
});

body.addEventListener("click", (e) => {
  console.log('body click capture')
}, true);

body.addEventListener("click", (e) => {
  console.log('body click bubble')
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

问:打印输出啥?

答:body click capture -> btn click capture -> btn click bubble -> body click bubble

参考: 深入理解浏览器的事件机制 (opens new window) DOM事件机制 (opens new window) 【前端词典】滚动穿透问题的解决方案 (opens new window)

编辑 (opens new window)
上次更新: 2025/07/20, 08:30:18
层合成
跨域

← 层合成 跨域→

最近更新
01
2024年
07-20
02
2023年
07-20
03
2022年
07-20
更多文章>
Theme by Vdoing | Copyright © 2025-2025 亮神 | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式