React中阻止事件冒泡的问题详析

前言
最近在研究react、redux等,网上找了很久都没有完整的答案,索性自己整理下,这篇文章就来给大家介绍了关于React阻止事件冒泡的相关内容,下面话不多说了,来一起看看详细的介绍吧
在正式开始前,先来看看 JS 中事件的触发与事件处理器的执行 。
JS 中事件的监听与处理
事件捕获与冒泡
DOM 事件会先后经历 捕获 与 冒泡 两个阶段 。捕获即事件沿着 DOM 树由上往下传递,到达触发事件的元素后,开始由下往上冒泡 。

React中阻止事件冒泡的问题详析

文章插图
事件处理器
默认情况下,事件处理器是在事件的冒泡阶段执行,无论是直接设置元素的 onclick 属性还是通过 EventTarget.addEventListener() 来绑定,后者在没有设置 useCapture 参数为 true 的情况下 。
考察下面的示例:
React中阻止事件冒泡的问题详析

文章插图
输出:
React中阻止事件冒泡的问题详析

文章插图
阻止事件的冒泡
通过调用事件身上的 stopPropagation() 可阻止事件冒泡,这样可实现只我们想要的元素处理该事件,而其他元素接收不到 。
React中阻止事件冒泡的问题详析

文章插图
输出:
React中阻止事件冒泡的问题详析

文章插图
一个阻止冒泡的应用场景
常见的弹窗组件中,点击弹窗区域之外关闭弹窗的功能,可通过阻止事件冒泡来方便地实现,而不用这种方式的话,会引入复杂的判断当前点击坐标是否在弹窗之外的复杂逻辑 。
React中阻止事件冒泡的问题详析

文章插图
但如果你尝试在 React 中实现上面的逻辑,一开始的尝试会让你怀疑人生 。
React 下事件执行的问题
了解了 JS 中事件的基础,一切都没什么难的 。在引入 React 后,,事情开始起变化 。将上面阻止冒泡的逻辑在 React 里实现一下,代码大概像这样:
React中阻止事件冒泡的问题详析

文章插图
输出:
React中阻止事件冒泡的问题详析

文章插图
document 上的事件处理器正常执行了,并没有因为我们在按钮里面调用 event.stopPropagation() 而阻止 。
那么问题出在哪?
React 中事件处理的原理
考虑下面的示例代码并思考点击按钮后的输出 。
React中阻止事件冒泡的问题详析

文章插图
现在对代码做一些变动,在 body 的事件处理器中把冒泡阻止,再思考其输出 。
React中阻止事件冒泡的问题详析

文章插图
下面是剧透环节,如果你懒得自己实验的话 。
点击按钮后的输出:
React中阻止事件冒泡的问题详析

文章插图
bdoy 上阻止冒泡后,你可能会觉得,既然 body 是按钮及按钮容器的父级,那么按钮及容器的事件会正常执行,事件到达 body 后,body 的事件处理器执行,然后就结束了 。document 上的事件处理器一个也不执行 。
事实上,按钮及按钮容器上的事件处理器也没执行,只有 body 执行了 。
输出:
React中阻止事件冒泡的问题详析

文章插图
【React中阻止事件冒泡的问题详析】通过下面的分析,你能够完全理解上面的结果 。
SyntheticEvent
React 有自身的一套事件系统,叫作 SyntheticEvent 。叫什么不重要,实现上,其实就是通过在 document 上注册事件代理了组件树中所有的事件(facebook/react#4335),并且它监听的是 document 冒泡阶段 。你完全可以忽略掉 SyntheticEvent 这个名词,如果觉得它有点让事情变得高大上或者增加了一些神秘的话 。

推荐阅读