当前位置: 首页 > 编程日记 > 正文

窥探react事件

写在前面

本文源于本人在学习react过程中遇到的一个问题;本文内容为本人的一些的理解,如有不对的地方,还请大家指出来。本文是讲react的事件,不是介绍其api,而是猜想一下react合成事件的实现方式

遇到的问题

class EventTest extends Component {handleParentClick(e) {console.log('click parent div');}handleChildClick(e) {e.stopPropagation();console.log('click child div');}componentDidMount() {document.querySelector('.parent').addEventListener('click', this.handleParentClick);}render() {return (<div className="parent"><div className="child" onClick={this.handleChildClick}></div></div>);}
}

上述代码render出来后,尝试点击一下div.child,诡异的现象产生了:

clipboard.png

控制台中输出如上图所示,这完全不符合浏览器的事件执行啊,我所期望的是指输出click child div,因为已经利用了e.stopPropagation()来阻止冒泡,说明阻止冒泡失效了,但是仅仅如此吗,可以发现的是首先输出的是click parent div(wtf)。

解决问题

为了解决上述问题,先来了解下react的事件,react事件是合成事件,为原生事件的一个子集,仅仅是进行了一个跨浏览器的封装。但是真的只有这么简单?图样图森破。
利用控制台,看下div.child对应的事件处理函数:

clipboard.png

一个空函数,事件的监听函数不是所定义的handleChildClick,而是emptyFunction,也就是说react没有在真实的DOM节点上绑定事件(在DOM节点上绑定事件比较消耗内存,因为当dom节点被remove后,虽然不存在与dom tree中,但是仍存在与内存中,需要手动remove事件orchild = null),react的合成事件利用的是事件代理方式实现,也就是说会将事件监听器绑定到整个文档document上,是不是这样呢?来验证一下,利用chrome:

clipboard.png

可以发现,document上的确被绑定了click事件,dom节点的真实的事件处理函数全部以一个特定的结构存储在了内存中,当点击div.child时,这时其事件处理函数为emptyFunction,执行这个函数无任何作用,按照浏览器标准事件模型,开始向上冒泡,这时到了div.parent,于是输出了click parent div,一直向上到了document,这时根据e.target进行处理,而react并不会根据dom层级式传播那样遍历virtual dom结构,这样有时遍历的层级会很多,而且会有很多的无效遍历。

react是怎么做的呢?

react依靠每个React component各自独立的id来编码这个层级。这样就能通过简单的字符串操作来获取所有父级 component 的父级内容,再把事件监听存储在hashmap当中,比如有如下结构并且为没一层div添加onClick

div.adiv.bdiv.c

当点击div.c时,处理方式:

clickBubbleListeners['a.b.c'](event);
clickBubbleListeners['a.b'](event);
clickBubbleListeners['a'](event);

在合成事件中用e.stopPropagation只能阻断上述冒泡过程。

结论

由此可以看出:

  • 阻止react事件冒泡的行为只能用于react合成事件中,对于原生事件无效(合成事件中的e.stopPropagation与原生事件中的e.stopPropagation并不是一回事)

  • 阻止原生事件的冒泡行为,可以阻止react合成事件的传播(根本不会冒泡到document上,所以不会触发react的合成事件)

  • 在写react时,最好不要将合成事件与原生事件混用

参考

本文部分参考自IMWeb—React事件初探

相关文章:

Python内置方法

一、常用的内置方法 1、__new__ 和 __init__&#xff1a; __new__ 构造方法 、__init__初始化函数1、__new__方法是真正的类构造方法&#xff0c;用于产生实例化对象&#xff08;空属性&#xff09;。重写__new__方法可以控制对象的产 生过程。也就是说会通过继承object的new方…

【OpenCV 】Sobel 导数/Laplace 算子/Canny 边缘检测

canny边缘检测见OpenCV 【七】————边缘提取算子&#xff08;图像边缘提取&#xff09;——canny算法的原理及实现 1 Sobel 导数 1.1.1 原因 上面两节我们已经学习了卷积操作。一个最重要的卷积运算就是导数的计算(或者近似计算). 为什么对图像进行求导是重要的呢? 假设我…

RGB 转 HSV

#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> int main() {// 图像源读取及判断cv::Mat srcImage cv::imread("22.jpg");if (!srcImage.data) …

2017.1.9版给信息源新增:max_len、max_db字段

2017.1.8a版程序给信息源增加max_len、max_db字段&#xff0c;分别用于控制&#xff1a;获取条数、数据库保留条数。 max_len的说明见此图&#xff1a; max_db的说明见此图&#xff1a; 当max_len和max_db的设置不合理时&#xff08;比如max_len大于max_db&#xff0c;会导致反…

索引使用的几个原则

索引的使用尽量满足以下几个原则&#xff1a; 全值匹配最左前缀不在索引列上做任何操作(包括但不限于&#xff0c;计算&#xff0c;函数&#xff0c;类型转换)&#xff0c;会导致对应列索引失效。不适用索引中范围条件右边的列尽量使用覆盖索引使用不等于或者not in 的时候回变…

【OpenCV 】Remapping 重映射¶

目录 1.1目标 1.2 理论 1.3 代码 1.4 运行结果 1.1目标 展示如何使用OpenCV函数 remap 来实现简单重映射. 1.2 理论 把一个图像中一个位置的像素放置到另一个图片指定位置的过程. 为了完成映射过程, 有必要获得一些插值为非整数像素坐标,因为源图像与目标图像的像素坐标…

C# GUID的使用

GUID&#xff08;全局统一标识符&#xff09;是指在一台机器上生成的数字&#xff0c;它保证对在同一时空中的所有机器都是唯一的。通常平台会提供生成GUID的API。生成算法很有意思&#xff0c;用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字。GUID的唯一缺陷在于生…

文件名有规则情况读取

#include <iostream> #include <stdio.h> #include <stdlib.h> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace cv; using namespace std; int main() {// 定义相关参数const int num 4;char…

编写自己的SpringBoot-starter

2019独角兽企业重金招聘Python工程师标准>>> 前言 原理 首先说说原理&#xff0c;我们知道使用一个公用的starter的时候&#xff0c;只需要将相应的依赖添加的Maven的配置文件当中即可&#xff0c;免去了自己需要引用很多依赖类&#xff0c;并且SpringBoot会自动进行…

【OpenCV 】直方图均衡化,直方图计算,直方图对比

目录 1.直方图均衡化 1.1 原理 1.2 直方图均衡化 1.3 直方图均衡化原理 1.4 代码实例 1.5 运行效果 2. 直方图计算 2.1 目标 2.2 直方图 2.3 代码实例 2.4 运行结果 3 直方图对比 3.1 目标 3.2 原理 3.3 代码 3.4 运行结果 1.直方图均衡化 什么是图像的直方图和…

c语言实现线性结构(数组与链表)

由于这两天看了数据结构&#xff0c;所以又把大学所学的c语言和指针"挂"起来了。本人菜鸟一枚请多多指教。下面是我这两天学习的成果&#xff08;数组和链表的实现&#xff0c;用的是c语言哦&#xff01;哈哈&#xff09;。&#xff08;一&#xff09;数组的实现和操…

OTSU 二值化的实现

#include <stdio.h> #include <string> #include "opencv2/highgui/highgui.hpp" #include "opencv2/opencv.hpp" using namespace std; using namespace cv; // 大均法函数实现 int OTSU(cv::Mat srcImage) {int nCols srcImage.cols;int nR…

vivo7.0系统机器(亲测有效)激活Xposed框架的教程

对于喜欢搞机的机友来说&#xff0c;常常会使用到Xposed框架和种种功能牛逼的模块&#xff0c;对于5.0以下的系统版本&#xff0c;只要手机能获得Root权限&#xff0c;安装和激活Xposed框架是异常轻松的&#xff0c;但随着系统版本的升级&#xff0c;5.0以后的系统&#xff0c;…

【OpenCV 】反向投影

目录 1 目标 2原理&#xff1a;什么是反向投影&#xff1f; 3 代码实现 4 实现结果 1 目标 什么是反向投影&#xff0c;它可以实现什么功能&#xff1f; 如何使用OpenCV函数 calcBackProject 计算反向投影&#xff1f; 如何使用OpenCV函数 mixChannels 组合图像的不同通道…

Linux编程之自定义消息队列

我这里要讲的并不是IPC中的消息队列&#xff0c;我要讲的是在进程内部实现自定义的消息队列&#xff0c;让各个线程的消息来推动整个进程的运动。进程间的消息队列用于进程与进程之间的通信&#xff0c;而我将要实现的进程内的消息队列是用于有序妥当处理来自于各个线程请求&am…

threshold 二值化的实现

#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" int main( ) {// 读取源图像及判断cv::Mat srcImage cv::imread("..\\images\\hand1.jpg");if( !srcImage.data ) return 1;// 转化为灰度图像cv::Mat srcGray…

如何定时备份数据库并上传七牛云

前言&#xff1a; 这篇文章主要记录自己在备份数据库文件中踩的坑和解决办法。 服务器数据库备份文件之后上传到七牛云 备份数据库文件在服务器根目录下 创建 /backup/qiniu/.backup.sh #!/bin/bash# vuemall 数据库名称 # blog_runner vuemall 的管理用户# admin vuem…

【OpenCV 】计算物体的凸包/创建包围轮廓的矩形和圆形边界框/createTrackbar添加滑动条/

目录 topic 1:模板匹配 topic 2:图像中寻找轮廓 topic 3:计算物体的凸包 topic 4:轮廓创建可倾斜的边界框和椭圆 topic 5:轮廓矩 topic 6:为程序界面添加滑动条 3.1 目标 3.2 代码实例1 3.3 代码实例2 3.4 实例3运行结果 3.5 运行结果 topic 1:模板匹配 topic 2:图…

开源:Angularjs示例--Sonar中项目使用语言分布图

在博客中介绍google的Angularjs 客户端PM模式框架很久了&#xff0c;今天发布一个关于AngularJs使用是简单示例SonarLanguage(示例位于Github&#xff1a;https://github.com/greengerong/SonarLanguage)。本项目只是一个全为客户端的示例项目。项目的初始是我想看看在公司的项…

adaptiveThreshold 阈值化的实现

#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" int main( ) {// 图像读取及判断cv::Mat srcImage cv::imread("..\\images\\hand1.jpg");if( !srcImage.data ) return 1;// 灰度转换cv::Mat srcGray;cv::cvt…

hashMap传入参数,table长度为多少

前言 我的所有文章同步更新与Github--Java-Notes,想了解JVM&#xff0c;HashMap源码分析&#xff0c;spring相关&#xff0c;剑指offer题解&#xff08;Java版&#xff09;&#xff0c;可以点个star。可以看我的github主页&#xff0c;每天都在更新哟。 邀请您跟我一同完成 rep…

【OpenCV】图像/视频相似度测量PSNR( Peak signal-to-noise ratio) and SSIM,视频/图片转换

目录 1 目标 2 原理 2.1 图像比较 - PSNR and SSIM 3 代码 3.1如何读取一个视频流&#xff08;摄像头或者视频文件)&#xff1f; 3 运行效果 视频/图片转换&#xff1a; 如何用OpenCV创建一个视频文件用OpenCV能创建什么样的视频文件如何释放视频文件当中的某个颜色通道…

struts2提交list

2019独角兽企业重金招聘Python工程师标准>>> Action: private List<User> users; jsp: <input type"text" name"users[0].name" value"aaa" /> <input type"text" name"users[1].name" value&q…

双阈值法的实现

#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" int main( ) {// 图像读取及判断cv::Mat srcImage cv::imread("..\\images\\hand1.jpg");if( !srcImage.data ) return 1;// 灰度转换cv::Mat srcGray;cv::cvt…

设计模式 小记

观察者模式 1.被观察者是单例模式。 生成这模式 1.Director中对于Builder的引用不一定是Strong&#xff0c;根据情况也有可能是Copy。 2.Director 聚合 Builder&#xff0c; 所以Builder本身可以单独拿出来使用。 转载于:https://juejin.im/post/5ca8c24df265da3094116c18

【MATLAB】————matlab raw图转bmp实现

image_path [layer_3_list_folder,\,layer_3_list_name]; img_raw_path fopen(image_path,r);%%打开图像 img_raw fread(img_raw_path,[Width,Height],uint16);% uchar为无符号字符型 mg_raw uint8(img_raw);%%unit8表示无符号整数&#xff0c;范围0-255&#xff0c;u…

人工手动冷备不完全恢复介绍(purge表不完全恢复)

不完全恢复不完全恢复的基本类型&#xff1a;1&#xff09;基于时间点 &#xff08;until time): 使整个数据库恢复到过去的一个时间点前2&#xff09;基于scn &#xff08;until change&#xff09;&#xff1a; 使整个数据库恢复到过去的某个SCN前3&#xff09;基于cancel (u…

半阈值法的实现

#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <iostream> using namespace std; using namespace cv; int main( ) {// 读取源图像及判断cv::Mat srcImage cv::imread("..\\images\\hand1.jpg&q…

novaclient的api调用流程与开发

novaclient的api调用流程与开发 2015年07月05日 19:27:17 qiushanjushi 阅读数&#xff1a;3915 http://blog.csdn.net/tpiperatgod/article/details/18375387?utm_sourcetuicool 另一个地址&#xff1a;http://neuromancer.sinaapp.com/?p64 从nova client的入口查看 cat /u…

【C++】 保存内容到文件工具

1. c 输出到文件 // save mean distance between center and descriptorsstd::string filename configuration_.debug_output_path() "ref_max_mean_distance.txt";FILE* fp fopen(filename.c_str(), "w");try {if (fp nullptr) {return error::Failed…