博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
诡异!React stopPropagation失灵
阅读量:7230 次
发布时间:2019-06-29

本文共 2185 字,大约阅读时间需要 7 分钟。

前言

先来看这

故事的开头是这样的:写代码的过程中,发现在内层用stopPropagation阻止绑定在document上的事件的时候,是没办法做到的,只可以阻止outClick事件的触发。

class ExampleApplication extends React.Component {    componentDidMount() {        document.addEventListener('click', () => {            alert('document click');        })    }    outClick(e) {        console.log(e.currentTarget);        alert('outClick');    }        onClick(e) {        console.log(e.currentTarget);        alert('onClick');        e.stopPropagation();    }    render() {        return 
}}

关于这个问题的解释,网上五花八门,有些将其归结为是由于事件委托的原因,例如这篇里说

我们直接在jsx模板上绑定的事件,都是委托在了document上,那自然要比直接在dom上绑定的事件慢了,等document收到事件后才去e.stopPropagation(),太晚了

其实从上面例子的输出: 由'onClick',再到'document click'可知,其实原生document上绑定的事件时最后执行的,所以并不是因为document收到事件快慢的原因而导致这个问题。

真相

真相只有一个,那就是:

出现上述bug的主要原因是混用浏览器原生事件跟React合成事件

详细解释:React有自己的一套事件处理机制,它会将所有的事件都绑定在document上,然后再用dispatchEvent统一分发,这时候分发的是合成事件

onClick(e)这时候拿到的e其实是合成事件,只能阻止合成事件的冒泡。

举个栗子来验证一下

class ExampleApplication extends React.Component {    componentDidMount() {        document.addEventListener('click', () => {            alert('document click');        })        document.getElementById('div1').addEventListener('click', () => {            alert('原生outClick');        })    }    outClick(e) {        console.log(e.currentTarget);        alert('合成outClick');    }        onClick(e) {        console.log(e.currentTarget);        alert('onClick');        e.stopPropagation();    }    render() {        return 
}}

做了点小改动,就是外层的div绑定的函数用原生的方式跟jsx的方式都绑定一次,所以最终的输出为

'原生outClick', 'onClick','document click'

所以button回调函数里的stopPropagation只能阻止合成事件的冒泡,而对于原生绑定的,则不行。

解决方法

解决方法有几种,我个人认为最简单的就是直接在onClick里利用[event.stopImmediatePropagation()][2]。原理是这样的:

对于例子一里,document其实绑定了两个事件:

// react 合成事件, dispatchEvent里面执行回调函数document.addEventListener('click', dispatchEvent);// 浏览器原生document.addEventListener('click', () => {   alert('document click');})

dispatchEvent里的stopImmediatePropagation可以使得绑定在document上的其他事件就不会被触发

onClick(e) {        console.log(e.currentTarget);        alert('onClick');        e.nativeEvent.stopImmediatePropagation();    }

当然本篇文章只是为了抛砖引玉,重点是下一篇的,欢迎继续收看。

转载地址:http://iycfm.baihongyu.com/

你可能感兴趣的文章
我的友情链接
查看>>
lvs+keepalived+nginx+tomcat高可用高性能集群部署
查看>>
实验:搭建主DNS服务器
查看>>
org.gjt.mm.mysql.Driver与com.mysql.jdbc.Driver区别
查看>>
部署exchange2010三合一:之五:功能测试
查看>>
nginx编译安装参数
查看>>
代码托管
查看>>
第一次给ThinkPHP5核心框架提pull request的完整过程
查看>>
U-Mail邮件系统何以誉为信息整合中转枢纽
查看>>
强大的vim配置文件,让编程更随意
查看>>
崛起于Springboot2.X之配置文件详解(10)
查看>>
定时执行程序-Quartz简单实例
查看>>
【CF 应用开发大赛】MyfCMS系统
查看>>
windows下kangle虚拟主机-架设java空间的教程及心得
查看>>
Discuz! X2.5:文件目录结构
查看>>
我的友情链接
查看>>
TCP/IP协议及首部初了解
查看>>
防火墙iptables
查看>>
CUDA搭建
查看>>
memcached与PostgreSQL缓存命中机制
查看>>