React 中阻止事件冒泡的问题
在正式开始前,先来看看 JS 中事件的触发与事件处理器的执行。 JS 中事件的监听与处理事件捕获与冒泡DOM 事件会先后经历 捕获 与 冒泡 两个阶段。捕获即事件沿着 DOM 树由上往下传递,到达触发事件的元素后,开始由下往上冒泡。
事件处理器默认情况下,事件处理器是在事件的冒泡阶段执行,无论是直接设置元素的 考察下面的示例: <button onclick="btnClickHandler(event)">CLICK ME</button> 输出:
阻止事件的冒泡通过调用事件身上的 <button onclick="btnClickHandler(event)">CLICK ME</button> 输出:
一个阻止冒泡的应用场景常见的弹窗组件中,点击弹窗区域之外关闭弹窗的功能,可通过阻止事件冒泡来方便地实现,而不用这种方式的话,会引入复杂的判断当前点击坐标是否在弹窗之外的复杂逻辑。 document.addEventListener("click", () => { 但如果你尝试在 React 中实现上面的逻辑,一开始的尝试会让你怀疑人生。 React 下事件执行的问题了解 JS 中事件的基础后,会觉得一切都没什么复杂。但在引入 React 后,事情开始起变化。将上面阻止冒泡的逻辑在 React 里实现一下,代码大概像这样: function App() { 输出:
document 上的事件处理器正常执行了,并没有因为我们在按钮里面调用 那么问题出在哪? React 中事件处理的原理考虑下面的示例代码并思考点击按钮后的输出。 import React, { useEffect } from "react"; 现在对代码做一些变动,在 body 的事件处理器中把冒泡阻止,再思考其输出。 document.body.addEventListener("click", event => { 下面是剧透环节,如果你懒得自己实验的话。 点击按钮后的输出:
bdoy 上阻止冒泡后,你可能会觉得,既然 body 是按钮及按钮容器的父级,那么按钮及容器的事件会正常执行,事件到达 body 后, body 的事件处理器执行,然后就结束了。 document 上的事件处理器一个也不执行。 事实上,按钮及按钮容器上的事件处理器也没执行,只有 body 执行了。 输出:
通过下面的分析,你能够完全理解上面的结果。 SyntheticEventReact 有自身的一套事件系统,叫作 SyntheticEvent。叫什么不重要,实现上,其实就是通过在 document 上注册事件代理了组件树中所有的事件(facebook/react#4335),并且它监听的是 document 冒泡阶段。你完全可以忽略掉 SyntheticEvent 这个名词,如果觉得它有点让事情变得高大上或者增加了一些神秘的话。 除了事件系统,它有自身的一套,另外还需要理解的是,界面上展示的 DOM 与我们代码中的 DOM 组件,也是两样东西,需要在概念上区分开来。 所以,当你在页面上点击按钮,事件开始在原生 DOM 上走捕获冒泡流程。React 监听的是 document 上的冒泡阶段。事件冒泡到 document 后,React 将事件再派发到组件树中,然后事件开始在组件树 DOM 中走捕获冒泡流程。 现在来尝试理解一下输出结果:
理解 React 是通过监听 document 冒泡阶段来代理组件中的事件,这点很重要。同时,区分原生 DOM 与 React 组件,也很重要。并且,React 组件上的事件处理器接收到的 紧接着的代码的改动中,我们在 body 上阻止了事件冒泡,这样事件在 body 就结束了,没有到达 document,那么 React 的事件就不会被触发,所以 React 组件树中,按钮及容器就没什么反应。如果没理解到这点,光看表象还以为是 bug。 进而可以理解,如果在 document.addEventListener("click", event => { 输出:
所以,虽然都是监听 document 上的点击事件,但 解答前面按钮未能阻止冒泡的问题如果你已经忘了,这是相应的代码及输出。function App() { 输出:
到这里,已经可以解答为什么 React 组件中 button 的事件处理器中调用 问题的解决要解决这个问题,这里有不止一种方法。 用
|
React 中阻止事件冒泡的问题的更多相关文章
- JQuery中阻止事件冒泡的两种方式及其区别
JQuery 提供了两种方式来阻止事件冒泡. 方式一:event.stopPropagation(); $("#div1").mousedown(function(event){ ...
- JQuery中阻止事件冒泡方式及其区别
JQuery 提供了两种方式来阻止事件冒泡. 方式一:event.stopPropagation(); $("#div1").mousedown(function( ...
- js中阻止事件冒泡和浏览器默认行为
在使用javascript编程时会遇到一个问题,就是当你给html添加事件时,由于浏览器默认的为冒泡型事件触发机制,所以会触发你不想触发的事件.那么通过如下的函数可以解决这个问题.[兼容IE和FF] ...
- angularjs中阻止事件冒泡,以及指令的注意点
appModule.directive('newStr',function(){ return{ restrict:'AE', //阻止事件冒泡需要加$event参数 template:`<di ...
- Html 中阻止事件冒泡的三种方法比较
A:return false --->In event handler ,prevents default behavior and event bubbing . return ...
- jQuery阻止事件冒泡的例子
下面给给各位朋友稍加整理了一jquery中阻止事件冒泡的一些例子,我们知道JQuery 提供了两种方式来阻止事件冒泡,但我们简单的利用它来做一些应用可能不深入或不理解,下面整理了更详细的方法,有兴趣的 ...
- react 阻止事件冒泡
前言 在学习react阻止事件冒泡,需要先了解 合成事件 和 原生事件 合成事件:在jsx中直接绑定的事件,就是合成事件: 原生事件: 通过js原生代码绑定的事件,就是原生事件: react事件:re ...
- React阻止事件冒泡的正确打开方式
需求:点击导航list按钮出现侧弹框,点击空白处弹框消失 问题:绑定空白处的点击事件到document上,但是非空白处的点击也会触发这个点击事件,在react中如何阻止事件冒泡? 解决方法:e.sto ...
- JS中的事件冒泡(Bubble)和事件捕获(capture)以及如何阻止事件的冒泡
对“捕获”和“冒泡”这两个概念,通常我们对冒泡了解和使用的会更多一些,因为在我们使用的所有浏览器中,都支持事件冒泡 ,即事件由子元素向祖先元素传播的,就 像气泡从水底向水面上浮一样.而在像firefo ...
随机推荐
- WSL Windows Subsystem for Linux安装指南
见官方文档: https://msdn.microsoft.com/en-us/commandline/wsl/install_guide
- [ SSH框架 ] Struts2框架学习之三(OGNl和ValueStack值栈学习)
一.OGNL概述 1.1 什么是OGNL OGNL的全称是对象图导航语言( object-graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可 ...
- C#本质论笔记
第一章 C#概述 1.1 Helo,World 学习一种新语言最好的办法就是动手写程序. C#编译器创建的.exe程序是一个程序集(Assembly),我们也可以创建能由另一个较大的程序 ...
- GitHub学习笔记:分支管理
GitHub对于每个开发版本都需要有一个分支,默认的分支是master往往被大家保留下来作为主分支,分支类似于进程的一个指针,往往在master这个稳定的主干版本上分出一个或多个正在开发的分支版本,开 ...
- centos下网络的配置
1.网络模式要进行使用NAT,要连网的话,要配置好设置:网络要进行一下共享到虚拟机 进入vi /etc/sysconfig/network-scripts/ifcfg-eth0 把里面的onboo ...
- UML类图10分钟快速入门 - From 圣杰
虚线箭头指向依赖: 实线箭头指向关联: 虚线三角指向接口: 实线三角指向父类: 空心菱形能分离而独立存在,是聚合: 实心菱形精密关联不可分,是组合: 原文作者:圣杰 原文地址:http://www.j ...
- 洛谷 P1069 解题报告
P1069 细胞分裂 题目描述 \(Hanks\)博士是\(BT\) (\(Bio-Tech\),生物技术) 领域的知名专家.现在,他正在为一个细胞实验做准备工作:培养细胞样本. \(Hanks\) ...
- 适合Python 新手的5大练手项目,你练了么?
接下来就给大家介绍几种适合新手的练手项目. 0.算法系列-排序与查找 Python写swap很方便,就一句话(a, b = b, a),于是写基于比较的排序能短小精悍.刚上手一门新语言练算法最合适不过 ...
- [CVPR2017] Weakly Supervised Cascaded Convolutional Networks论文笔记
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px "Helvetica Neue"; color: #042eee } p. ...
- 创建第一个core项目(netCore学习笔记1)
1.安装 core和netFramework其实是相对独立的,但是core的IDE是在vs2017才开始支持,而vs2017的安装环境必须搭配.net4.6,所以: Step1:安装.net4.6 S ...