首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

什么捕获冒泡?难道浏览器是鱼吗?

身为一个前端小混混,在开发中遇到凡是需要与用户互动或是需要由用户触发的功能,总是离不开事件处理。

今天聊聊浏览器的 DOM 事件传递机制。

DOM 事件

在浏览器的 Javascript 引擎解析 HTML、SVG 时,会将内容分析成一个个的 DOM (Document Object Model),当用户与 DOM 产生互动时,则是通过 DOM 上注册的事件监听器,去触发某个事件。

例如常见的 、,输入框的 、、 等,都是常用的事件类型。

事件监听

例如我们曾经最熟悉的 jQuery,我们会用这样的方式去注册事件监听:

但 jQuery 已经成为明日黄花;在现代框架中,Vue 对注册事件监听器提供了一些语法糖,让你写起来很轻松:

React 除了语法糖外,底层还将 DOM 事件再封装一层,并帮你全都代理到 上,性能很不错:

当然不管是什么框架,底层都等同于通过 Javascript 进行操作:

事件代理

前面说到 React 会帮你把事件代理到 document 上,这是什么意思呢?

看这个的 简单小例子,点击按钮新增 时,会一并注册事件监听:

这样很直观,但缺点也很明显;每新增一个元素,都会创建一个事件监听,当数量增多,造成的内存消耗也会十分可观:

如果把事件监听注册在外层的 ,并在点击事件触发时判断触发到到的是谁:

通过事件代理,无论内容有多少,事件监听都只会有一组,效能得到了很大的提升。

移除事件监听

注册事件监听器很方便,但在确定不会再使用监听器时,要记得通过 将事件监听移除。如果留下了无用的事件监听器,将会造成内存的浪费,对性能有很大的损害。

大家应该注意到了,在前面那个简易的小例子中并没有移除事件监听,而且每创建一个新的子元素,都会同时创建新的函数:

比较好的写法是把匿名函式抽出来,并在移除子元素时一并移除事件监听器:

在 Vue 和 React 等主流网页框架中,只要是使用内建的语法注册的事件监听,它们都会自动在无用的时候移除,可以放心使用;如果是自己实现事件监听,务必要记得移除。

捕获与冒泡

跑题太远了,所以到底什么是捕获与冒泡?

根据 W3C 所定义的 Event Flow:

DOM Event 框架

浏览器中的事件传递过程分成三个阶段:

捕获阶段:由 DOM 树的最外层依序向内,过程中触发个别元素的捕获阶段事件监听。

目标阶段:到达事件目标,按照注册顺序触发事件监听。

冒泡阶段:由事件目标依序向外,过程中触发个别元素的冒泡阶段事件监听。

这就是刚刚提到的事件代理的机制了;在事件传递过程中,捕获冒泡阶段必然会经过外层元素,因此可以将事件监听注册到外层元素上。

另外,当我们在用 注册事件监听器时,可以传递第三个参数,指定这个事件要在什么阶段触发:

如上图所示, 当一个 DOM 事件发生时,会由最外层的 开始依次向内传递事件,一直传到我们的事件目标,触发完目标上注册的事件监听,再进入冒泡阶段反向传递;由指定触发的阶段,就能确定执行的顺序了。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20201026A0E6FM00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券