摘要:解决问题为了解决上述问题,先来了解下的事件,事件是合成事件,为原生事件的一个子集,仅仅是进行了一个跨浏览器的封装。参考本文部分参考自事件初探
写在前面
本文源于本人在学习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 (); } }
上述代码render出来后,尝试点击一下div.child,诡异的现象产生了:
控制台中输出如上图所示,这完全不符合浏览器的事件执行啊,我所期望的是指输出click child div,因为已经利用了e.stopPropagation()来阻止冒泡,说明阻止冒泡失效了,但是仅仅如此吗,可以发现的是首先输出的是click parent div(wtf)。
解决问题为了解决上述问题,先来了解下react的事件,react事件是合成事件,为原生事件的一个子集,仅仅是进行了一个跨浏览器的封装。但是真的只有这么简单?图样图森破。
利用控制台,看下div.child对应的事件处理函数:
一个空函数,事件的监听函数不是所定义的handleChildClick,而是emptyFunction,也就是说react没有在真实的DOM节点上绑定事件(在DOM节点上绑定事件比较消耗内存,因为当dom节点被remove后,虽然不存在与dom tree中,但是仍存在与内存中,需要手动remove事件orchild = null),react的合成事件利用的是事件代理方式实现,也就是说会将事件监听器绑定到整个文档document上,是不是这样呢?来验证一下,利用chrome:
可以发现,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.a div.b div.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事件初探
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/81111.html
摘要:仅对于组件,用于监听原生事件,而不是组件内部使用触发的事件。注意,你无法对中的赋值,因为已经自动为你进行了同步。 简介 在使用Vue进行开发的时候,大多数情况下都是使用template进行开发,使用template简单、方便、快捷,可是有时候需要特殊的场景使用template就不是很适合。因此为了很好使用render函数,我决定深入窥探一下。各位看官如果觉得下面写的有不正确之处还望看官...
摘要:而且默认带有执行的顺序是,,即便是内联的,依然具有属性。模块脚本只会执行一次必须符合同源策略模块脚本在跨域的时候默认是不带的。通常被用作脚本被禁用的回退方案。最后标签真的令人感到兴奋。 窥探 Script 标签 0x01 什么是 script 标签? script 标签允许你包含一些动态脚本或数据块到文档中,script 标签是非闭合的,你也可以将动态脚本或数据块当做 script 的...
摘要:而且默认带有执行的顺序是,,即便是内联的,依然具有属性。模块脚本只会执行一次必须符合同源策略模块脚本在跨域的时候默认是不带的。通常被用作脚本被禁用的回退方案。最后标签真的令人感到兴奋。 窥探 Script 标签 0x01 什么是 script 标签? script 标签允许你包含一些动态脚本或数据块到文档中,script 标签是非闭合的,你也可以将动态脚本或数据块当做 script 的...
摘要:所谓知其然还要知其所以然本文将分析的部分源码包括组件初始渲染的过程和组件更新的过程在这之前假设读者已经对有一定了解知道区别了解生命周期事务批量更新大致概念等如何分析源码代码架构预览首先我们找到在上的地址把版本的源码下来观察它的整体架构这 所谓知其然还要知其所以然. 本文将分析 React 15-stable的部分源码, 包括组件初始渲染的过程和组件更新的过程.在这之前, 假设读者已经:...
摘要:主要兼容的微信的浏览器,因为要在朋友圈来营销,总体来说,会偏设计以及动画些。 有一天,我们组内的一个小伙伴突然问我,你知道有一个叫重构工程师的岗位?这是干什么的?重构工程师 这个问题引发了我对前端领域发展的思考,所以我来梳理下前端领域的发展过程,顺便小小的预测下2017年的趋势。不想看回忆的,可以直接跳到后面看展望。 神说,要有光,就有了光 自1991年蒂姆·伯纳斯-李公开提及HTML...
阅读 600·2021-11-24 09:39
阅读 3448·2019-08-30 15:53
阅读 2472·2019-08-30 15:44
阅读 3212·2019-08-30 12:54
阅读 2181·2019-08-29 12:23
阅读 3265·2019-08-26 14:05
阅读 2052·2019-08-26 13:36
阅读 3387·2019-08-26 13:33