博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浅析React之事件系统(二)
阅读量:6303 次
发布时间:2019-06-22

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

上篇文章中,我们谈到了React事件系统的实现方式,和在React中使用原生事件的方法,那么这篇文章我们来继续分析下,看看React中合成事件和原生事件混用的各种情况。

上一个例子

在上篇文章中,我们举了个例子。为了防止大家不记得,我们来看看那个例子的代码。

class App extends React.Component {  constructor(props){    super(props);        this.state = {      show: false    }        this.handleClick = this.handleClick.bind(this)    this.handleClickImage = this.handleClickImage.bind(this);  }    handleClick(){   this.setState({     show: true   })  }    componentDidMount(){    document.body.addEventListener('click', e=> {      this.setState({        show: false      })    })  }    componentWillUnmount(){    document.body.removeEventListener('click');  }    handleClickImage(e){    console.log('in this ')    e.stopPropagation();  }    render(){    return (      
) }}ReactDOM.render(
, document.getElementById('root'));

这有什么问题呢? 问题就在于,如果我们点击image的内部依旧可以收起Image,那么这是为什么呢?这是因为我们及时点击了Image的内部,body上绑定的事件处理器依旧会执行,这样就让我们的image收起来了。那我们如果不想让image收起来改怎么做呢?

首先的想法是停止冒泡,如果我们在img-container中就停止冒泡了是不是就可以让image不消失了呢?比如这样:

...handleClickImage(e){    e.preventDefault();    e.stopPropagation();  }    render(){    return (      
) }...

在这里我们定义一个handleClickImage的方法,在其中我们执行取消默认行为和停止冒泡。那是似乎效果并不是我们想要的。因为阻止React事件冒泡的行为只能用于React合成事件中,没法阻止原生事件的冒泡。同样用React.NativeEvent.stopPropagation()也是无法阻止冒泡的。

如何解决这样的问题呢?首先,尽量的避免混用合成事件和原生事件。需要注意的点是:

  1. 阻止react 合成事件冒泡并不会阻止原生时间的冒泡,从上边的例子我们已经看到了,及时使用stopPropagation也是无法阻止原生时间的冒泡的。

  2. 第二点需要注意的是,取消原生时间的冒泡会同时取消React Event。并且原生事件的冒泡在react event的触发和冒泡之前。同时React Event的创建和冒泡是在原生事件冒泡到最顶层的component之后的。我们来看这个例子:

class App extends React.Component {    render(){   return 
; }}class GrandPa extends React.Component { constructor(props){ super(props); this.state = {clickTime: 0}; this.handleClick = this.handleClick.bind(this); } handleClick(){ console.log('React Event grandpa is fired'); this.setState({clickTime: new Date().getTime()})}; componentDidMount(){ document.getElementById('grandpa').addEventListener('click',function(e){ console.log('native Event GrandPa is fired'); }) } render(){ return (

GrandPa Clicked at: {this.state.clickTime}

) }}class Dad extends React.Component { constructor(props){ super(props); this.state = {clickTime:0}; this.handleClick=this.handleClick.bind(this); } componentDidMount(){ document.getElementById('dad').addEventListener('click',function(e){ console.log('native Event Dad is fired'); e.stopPropagation(); }) } handleClick(){ console.log('React Event Dad is fired') this.setState({clickTime: new Date().getTime()}) } render(){ return (

Dad Clicked at: {this.state.clickTime}

) }}class Son extends React.Component { constructor(props){ super(props); this.state = {clickTime:0}; this.handleClick=this.handleClick.bind(this); } handleClick(){ console.log('React Event Son is fired'); this.setState({clickTime: new Date().getTime()}) } componentDidMount(){ document.getElementById('son').addEventListener('click',function(e){ console.log('native Event son is fired'); }) } render(){ return (

Son Clicked at: {this.state.clickTime}

) }}ReactDOM.render(
, document.getElementById('root'));

在这个例子中我们有三个component,Son Dad,Grandpa。同时定义了React Event handler 和 native event handler,并在Dad的native Event handler中stopPropagation,当我们点击Son or Dad component的时候会发现,React Event handler并没有被trigger。

console里的output为:

"native Event son is fired""native Event Dad is fired"

这就说明native Event的停止冒泡可以阻断所有的React Event。所以即使我们是在Dad上停止冒泡的,依旧阻断了Son上的React Event。

同时如果我们把dad上的stopPropagation remove掉我们会看到如下结果:

"native Event son is fired""native Event Dad is fired""native Event GrandPa is fired""React Event Son is fired""React Event Dad is fired""React Event grandpa is fired"

这就说明React的合成时间是在原生事件冒泡到最顶层组件结束后才创建和冒泡的,也是符合React的原理,因为在是实现的时候React只是将一个Event listener 挂在了最顶层的组件上,其内部一套自己的机制进行事件的管理。

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

你可能感兴趣的文章
Oracle 11g password过期被锁定报道 ORA-28000 the account is locked
查看>>
【Struts2学习笔记(2)】Action默认值和配置Action于result各种转发类型
查看>>
轨磁条简介
查看>>
(算法)交错的字符串
查看>>
hdu 5471(状压DP or 容斥)
查看>>
oracle.jdbc.driver.OracleDriver和oracle.jdbc.OracleDriver这两个驱动的区别
查看>>
NSQ部署
查看>>
git常用命令记录
查看>>
IBM发布新一代云计算工具包MobileFirst Foundation
查看>>
唯品会HDFS性能挑战和优化实践
查看>>
大规模学习该如何权衡得失?解读NeurIPS 2018时间检验奖获奖论文
查看>>
大厂前端高频面试问题与答案精选
查看>>
我们用5分钟写了一个跨多端项目
查看>>
Visual Studio 15.4发布,新增多平台支持
查看>>
有赞透明多级缓存解决方案(TMC)设计思路
查看>>
如何设计高扩展的在线网页制作平台
查看>>
Git 2.5增加了工作树、改进了三角工作流、性能等诸多方面
查看>>
Swift 5将强制执行内存独占访问
查看>>
中台之上(二):为什么业务架构存在20多年,技术人员还觉得它有点虚?
查看>>
深度揭秘腾讯云低功耗广域物联网LPWAN 技术及应用
查看>>