欢迎学习交流!!!
持续更新中…

文章目录

  • 事件流
  • DOM事件流的几个阶段
  • React合成事件
    • React合成事件原理
    • 在react中使用原生事件方法
  • 合成事件和原生事件混合使用
    • 响应顺序
    • 阻止冒泡
  • 总结

事件流

'流’这个名词在JS中随处可见。像DOM事件流、React中的数据流等等。
‘流’是一种有方向的数据;事件流,是页面接受事件的顺序。

DOM事件流的几个阶段

  • 事件捕获阶段

当某个事件触发时,文档根节点最先接受到事件,然后根据DOM树结构向具体绑定事件的元素传递。该阶段为父元素截获事件提供了机会。
事件传递路径为:
window —> document —> body —> button

  • 目标阶段

具体元素已经捕获事件,之后事件开始向根节点冒泡。

  • 事件冒泡阶段

该阶段的开始即是事件的开始,根据DOM树结构由具体触发事件的元素向根节点传递。
事件传递路径:
button —> body —> document —> window

选择监听事件的阶段:

使用addEventListener函数在事件流的的不同阶段监听事件,

DOM.addEventListener(‘事件名称’,handleFn,Boolean);

第三个参数Boolean即代表监听事件的阶段:
为true时,在捕获阶段监听事件;
为false时,在冒泡阶段监听事件

事件冒泡和事件捕获:
HTML DOM中有两种事件传播方式,冒泡和捕获方式。事件传播是一种在事件发生时定义元素顺序的方法

  • 冒泡:从里到外
  • 捕获:从外到里

React合成事件

React在事件绑定时有一套自身的机制,就是合成事件。

react中事件绑定:
<div className="dome" onClick={this.handleClick}>
普通的事件绑定:
<div class="dome" onclick="handleClick()">

React合成事件机制:
React并不是将click事件直接绑定在dom上面,而是采用事件冒泡的形式冒泡到document上面,然后React将事件封装给正式的函数处理运行和处理。

React合成事件原理

若react事件绑定在真实的DOM节点上,一个DOM节点绑定过多事件处理函数,整个页面的响应和内存占用可能都会受到很大的影响。
React为了避免这类DOM事件的滥用,同时屏蔽底层不同浏览器之间的时间系统的差异,出现了一个中间层——SyntheticEvent。

  1. 当用户在为onClick添加函数时,React并没有将Click绑定到DOM上
  2. 而在document处监听所有支持的事件,当事件发生并冒泡至document处时,React将事件内容封装交给中间层 SyntheticEvent (负责所有事件合成)
  3. 然后使用统一的分发函数 dispatchEvent 将封装的事件内容交由真正的处理函数执行


注:
由于class的方法默认不会绑定this,若没有绑定this,调用this的时候为undefined

 export default class App extends React.Component {show(){console.log(this)  }render (){ return   <button onClick={ this.show }>点击</button>}

解决方法:

  • 在构造函数中使用bind绑定this。在构造函数constructor内绑定this,优点是只需要绑定一次,避免每次渲染时的重新绑定,函数在别处复用时也无需再次绑定
export default class App extends React.Component  {constructor(props) {super(props);this.show = this.show.bind(this);}show(){console.log(this)  }render() {return  <button onClick={ this.show }>点击</button>;}
}
  • 在调用的时候使用bind绑定this。直接绑定方法,缺点是每次渲染都会重新绑定一次bind
export default class App extends React.Component  {show(){console.log(this);}render() {return   <button onClick={this.show.bind(this)}>点击</button>}
}
  • 在调用时用箭头函数绑定this。箭头函数不仅仅是函数的“语法糖”,还自动绑定了定义此函数作用域的this,因此不需要再对它使用bind方法
export default class App extends React.Component {show(){console.log(this);}render() {return <button onClick={()=>this.show()}>点击</button>}
}

在react中使用原生事件方法

react封装了大多数的原生事件,但也有个例:

  • Modal开启以后点击其他空白区域需要关闭Modal
  • 引入了一些以原生事件实现的第三方库,并且互相之间需要有交互

由于原生事件需要绑定在真实DOM上,所以一般是在componentDidMount阶段/ref的函数执行阶段进行绑定操作,在componentWillUnmount阶段进行解绑操作以避免内存泄漏。

合成事件和原生事件混合使用

若业务场景中需要混合使用合成事件和原生事件,使用过程中需注意:

响应顺序

class Demo extends React.Component {componentDidMount() {const $this = ReactDOM.findDOMNode(this)$this.addEventListener('click', this.onDOMClick, false)}onDOMClick = evt => {console.log('dom event')}onClick = evt => {console.log('react event')}render() {return (<div onClick={this.onClick}>Demo</div>)}
}

分析:首先DOM事件监听器被执行,然后事件继续冒泡至document,合成事件监听器被执行。

阻止冒泡

如果在onDOMClick中调用evt.stopPropagation()方法,由于DOM事件被阻止冒泡了,无法到达document,所以合成事件自然不会被触发

export default class Test extends Component {componentDidMount() {const $parent = ReactDOM.findDOMNode(this);const $child = $parent.querySelector('.child');$parent.addEventListener('click', this.onParentDOMClick, false)$child.addEventListener('click', this.onChildDOMClick, false)}onParentDOMClick = evt => {console.log('parent dom event')}onChildDOMClick = evt => {console.log('child dom event')}onParentClick = evt => {console.log('parent react event')}onChildClick = evt => {evt.stopPropagation();console.log('child react event')}render() {return (<div onClick={this.onParentClick}><div className="child" onClick={this.onChildClick}>Demo</div></div>)}
}

onChildClick中调用evt.stopPropagtion(),合成事件不会被触发是因为React给合成事件封装的stopPropagation函数调用时给自己加了isPropagationStopped的标记位来确定后续监听器是否执行。

总结

  • class方法默认不会绑定this,需要在构造函数constructor内使用bind绑定this
  • 合成事件的监听器是统一注册在document上的,并且仅有冒泡阶段。所以原生事件的监听器响应总是比合成事件的监听器早
  • 阻止原生事件的冒泡后,会阻止合成事件的监听器执行

参考文章:

  • React-合成事件和原生事件的区别
  • React合成事件和DOM原生事件的区别

【React】合成事件和原生事件相关推荐

  1. vue中 点击事件的写法_vue中的事件:原生事件与自定义事件__Vue.js

    模板编译 processAttrs 对于ast attributes处理(v-on/@) 利用onRE与dirRE来捕获事件 这里最重要的就是dynamic的判断,vue中可以用动态参数来命名事件名称 ...

  2. react 八千字长文深入了解react合成事件底层原理,原生事件中阻止冒泡是否会阻塞合成事件?

    壹 ❀ 引 在前面两篇文章中,我们花了较大的篇幅介绍react的setState方法,在介绍setState同步异步时提到,在react合成事件中react对于this.state更新都是异步,但在原 ...

  3. React 合成事件

    文章借鉴 pingan8787 React合成事件 和 React合成事件官方文档 React 合成事件 一.概念介绍 React合成事件是React 模拟原生DOM事件所有能力 的一个事件对象. 根 ...

  4. 探索React合成事件

    探索 React 合成事件 一.什么是合成事件 React 合成事件(SyntheticEvent)是 React 模拟原生 DOM 事件所有能力的一个事件对象,即浏览器原生事件的跨浏览器包装器.它根 ...

  5. react合成事件和DOM原生事件的区别

    事件流 在了解事件之前先来看一下什么是事件流. '流'这个名词在JS中随处可见.像DOM事件流.React中的数据流等等. 其实,流就是一种有方向的数据:事件流,是页面接受事件的顺序. 一.DOM事件 ...

  6. React合成事件(阻止冒泡stopImmediatePropagation)

    文章目录 一.遇到的问题 问题描述 分析 二.React 合成事件 1.执行顺序 2.合成事件阻止冒泡 2.1e.stopPropagation 2.2 e.nativeEvent.stopImmed ...

  7. react div onclick叠加_深入学习 React 合成事件

    翁斌斌,微医云前端工程师,在程序员的修炼道路上永不止步. 以下分析基于React, ReactDOM 16.13.1版本 提出问题 我们借鉴一个比较典型的案例开始来分析React事件 export 从 ...

  8. 【React源码】(十六)React 合成事件

    React 合成事件 概览 从v17.0.0开始, React 不会再将事件处理添加到 document 上, 而是将事件处理添加到渲染 React 树的根 DOM 容器中. 引入官方提供的图片: 图 ...

  9. 彻底搞懂原生事件流和 React 事件流

    事件系统,业务开发中只要需要与用户进行交互,那么事件是必不可少的,dom 中存在很多事件,比如 click,scroll,focus 等等.我们将深入事件系统中,以及事件中常用的一些操作比如 prev ...

最新文章

  1. 城科会刘朝晖:从互联网大脑模型看城市大脑
  2. 十步图解CSS的position
  3. Android Studio开发RecyclerView遇到的各种问题以及解决(一)
  4. 利用Lucene.net搜索引擎进行多条件搜索的做法
  5. TCP_DEFER_ACCEPT
  6. SOA与云计算相结合推动企业发展
  7. 调用webservice超时问题的解决
  8. Oracle中删除用户和表空间的常见问题(比如:ORA-01940无法删除当前已连接用户的解决方案)
  9. sqlserver note
  10. SecureWatch和人工智能为疫情期间更安全有效地监控房地产开发提供助力
  11. 有关判读flex 模板载入是否结束的一些问题。
  12. 【c语言】小游戏程序——弹跳小球
  13. JSON 转换 Excel
  14. 笔记 GWAS 操作流程2-1:缺失质控
  15. 微波技术与天线_HFSS_微带贴片天线建模仿真
  16. mmdetection2.24.1修改backbone(使用mmcls和timm已有模型)
  17. 【设计模式】建造者模式
  18. 做单:第3章 骂人的客户
  19. 关于双通道CANFD记录仪的视频介绍
  20. 证券公司信息化5-我国证券公司交易系统的演化过程和主要阶段是怎样的?什么是卫星报盘系统?

热门文章

  1. C/C++ 实现strchr函数
  2. 昆明学院计算机网络期末试题,昆明学院校园网的组建剖析.doc
  3. IOS 翻译APP开发
  4. python对二维数组排序_python学习笔记:二维数组排序问题
  5. Markdown基本语法-超级全面
  6. sshpass的安装与使用
  7. 投资理财交易系统设计与开发
  8. [Python] 变量重分类(连续变量重分类、离散变量重分类)
  9. 免费软件中的零成本营销
  10. 一个来自普通大学的普通学生的不普通自述