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

在React中如何优雅的处理事件响应详解

在React中如何优雅的处理事件响应详解

前言

本文主要给大家介绍的是关于React处理事件响应的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍吧。

React中定义一个组件,可以通过React.createClass或者ES6的class。本文讨论的React组件是基于class定义的组件。采用class的方式,代码结构更加清晰,可读性强,而且React官方也推荐使用这种方式定义组件。

处理事件响应是Web应用中非常重要的一部分。React中,处理事件响应的方式有多种。

一、使用箭头函数

先上代码:

//代码1class MyComponent extends React.Component { render() { return (  <button onClick={()=>{console.log('button clicked');}}>  Click  </button> ); }}

当事件响应逻辑比较复杂时,再把所有的逻辑直接写在onClick的大括号内,就会导致render函数变得臃肿,不容易直观地看出组件render出的元素结构。这时,可以把逻辑封装成组件的一个方法,然后在箭头函数中调用这个方法。

如下所示:

//代码2class MyComponent extends React.Component { constructor(props) { super(props); this.state = {number: 0}; } handleClick() { this.setState({  number: ++this.state.number }); }  render() { return (  <div>  <div>{this.state.number}</div>  <button onClick={()=>{this.handleClick();}}>   Click  </button>  </div> ); }}

这种方式最大的问题是,每次render调用时,都会重新创建一个事件的回调函数,带来额外的性能开销,当组件的层级越低时,这种开销就越大,因为任何一个上层组件的变化都可能会触发这个组件的render方法。当然,在大多数情况下,这点性能损失是可以不必在意的。这种方式也有一个好处,就是不需要考虑this的指向问题,因为这种写法保证箭头函数中的this指向的总是当前组件。

二、使用组件方法

代码先:

//代码3class MyComponent extends React.Component { constructor(props) { super(props); this.state = {number: 0}; this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState({  number: ++this.state.number }); }  render() { return (  <div>  <div>{this.state.number}</div>  <button onClick={this.handleClick}>   Click  </button>  </div> ); }}

这种方式的好处是每次render,不会重新创建一个回调函数,没有额外的性能损失。需要注意的是,使用这种方式要在构造函数中为事件回调函数绑定this: this.handleClick = this.handleClick.bind(this) ,否则handleClick中的this是undefined。这是因为ES6 语法的缘故,ES6 的 Class 构造出来的对象上的方法默认不绑定到 this 上,需要我们手动绑定。每次都手动绑定this是不是有点蛋疼?好吧,让我们来看下一种方式。

三、属性初始化语法(property initializer syntax)

使用ES7的 property initializers,代码可以这样写:

//代码4class MyComponent extends React.Component { constructor(props) { super(props); this.state = {number: 0}; } handleClick = () => { this.setState({  number: ++this.state.number }); }  render() { return (  <div>  <div>{this.state.number}</div>  <button onClick={this.handleClick}>   Click  </button>  </div> ); }}

哈哈,再也不用手动绑定this了。但是你需要知道,这个特性还处于试验阶段,默认是不支持的。如果你是使用官方脚手架Create React App 创建的应用,那么这个特性是默认支持的。你也可以自行在项目中引入babel的transform-class-properties插件获取这个特性支持。

四、回调函数传参问题

事件的回调函数默认是会被传入一个事件对象Event作为参数的。如果我想传入其他参数给回调函数应该怎么办呢?

使用第一种方式的话很简单,直接传就可以了:

//代码5class MyComponent extends React.Component { constructor(props) { super(props); this.state = {  list: [1,2,3,4],  current: 1 }; }  handleClick(item,event) { this.setState({  current: item }); } render() { return (  <ul>  {this.state.list.map(   (item)=>(   <li className={this.state.current === item ? 'current':''}    onClick={(event) => this.handleClick(item, event)}>{item}   </li>   )  )}  </ul> ); }}

使用第二种方式的话,可以把绑定this的操作延迟到render中,在绑定this的同时,绑定额外的参数:

//代码6class MyComponent extends React.Component { constructor(props) { super(props); this.state = {  list: [1,2,3,4],  current: 1 }; }  handleClick(item) { this.setState({  current: item }); } render() { return (  <ul>  {this.state.list.map(   (item)=>(   <li className={this.state.current === item ? 'current':''}    onClick={this.handleClick.bind(this, item)}>{item}   </li>   )  )}  </ul> ); }}

使用第三种方式,解决方案和第二种基本一致:

//代码7class MyComponent extends React.Component { constructor(props) { super(props); this.state = {  list: [1,2,3,4],  current: 1 }; }  handleClick = (item) => { this.setState({  current: item }); } render() { return (  <ul>  {this.state.list.map(   (item)=>(   <li className={this.state.current === item ? 'current':''}    onClick={this.handleClick.bind(undefined, item)}>{item}   </li>   )  )}  </ul> ); }}

不过这种方式就有点鸡肋了,因为虽然你不需要通过bind函数绑定this,但仍然要使用bind函数来绑定其他参数。

关于事件响应的回调函数,还有一个地方需要注意。不管你在回调函数中有没有显式的声明事件参数Event,React都会把事件Event作为参数传递给回调函数,且参数Event的位置总是在其他自定义参数的后面。例如,在代码6和代码7中,handleClick的参数中虽然没有声明Event参数,但你依然可以通过arguments[1]获取到事件Event对象。

总结

三种绑定事件回调的方式,第一种有额外的性能损失;第二种需要手动绑定this,代码量增多;第三种用到了ES7的特性,目前并非默认支持,需要Babel插件的支持,但是写法最为简洁,也不需要手动绑定this。推荐使用第二种和第三种方式。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。

相关文章

Photoshop合成北欧小户型沙发摆放

Photoshop合成北欧小户型沙发摆放

动态,北欧,小户型,场景,电脑软件,本篇文章如何分析打造风格沙发情景案例技巧分享,在家装效果图上的效果很不错的说,喜欢的朋友一起来学习吧,学习一下设计的思路,可惜的是作者没有给素材,大家可以自己百度动手找找看吧。12 阅读全文教程结束,以上…

ASP.NET防止SQL注入的方法示例

ASP.NET防止SQL注入的方法示例

方法,示例,电脑软件,ASP,NET,本文实例讲述了ASP.NET防止SQL注入的方法。分享给大家供大家参考,具体如下:最近接手别人一个项目,发现存在SQL注入漏洞,因为不想改太多代码,所以那种参数法防注入呢我就用不着了。只能用传统的笨一点的办法了。1、新…

99%的程序员都会收藏的书单 你读过

99%的程序员都会收藏的书单 你读过

都会,书单,读过,程序员,几本,人丑就要多读书,颜值不够知识来凑,至少你可以用书籍来武装你的大脑,拯救你的人生。TIOBE编程语言排行榜前20的语言入门书籍推荐 01 顶级程序员必备书籍,雷军都点赞的书单!(点击这里,查看原文)拿到了一份雷军点赞的程序…

原生js获取left值和top值的三种方

原生js获取left值和top值的三种方

方法,原生,三种,电脑软件,top,在用js做动态效果时,通常需要获取元素绝对定位中的left和top属性值。比如做一个碰撞广告,就要不停的获取元素的top和left属性值。需要注意的事:取值的元素必须要设置position:absolute绝对定位属性,才能取的到left…

浅谈JavaScript中的属性:如何遍历

浅谈JavaScript中的属性:如何遍历

属性,遍历,浅谈,电脑软件,JavaScript,在JavaScript中,遍历一个对象的属性往往没有在其他语言中遍历一个哈希(有些语言称为字典)的键那么简单。这主要有两个方面的原因:一个是,JavaScript中的对象通常都处在某个原型链中,它会从一个或多个的上…

Photoshop 玻璃图标按钮

Photoshop 玻璃图标按钮

图标,玻璃,电脑软件,按钮,按钮图标,最终效果图1、新建文档,使用圆角矩形工具Alt键绘制一个圆角正方形,然后使用渐变工具设置下面两种颜色进行填充,该图层命名为:icon-bg ,效果如下图: 2、复制图层,命名为glass,改变填充为白色填充,透明度为50%,使用矩…

PS CS5怎么制作个性的课程表?

PS CS5怎么制作个性的课程表?

课程表,个性,电脑软件,PS,新的学期才刚开始,又有新的课程了,那么怎么用photoshop做一个带有背景的有自己特色的课程表呢?软件名称:Photoshop CS5 绿色版官方中文正式原版软件大小:104.06MB更新时间:2014-06-011、首先打开excel,建立一个课程表。因…

利用js编写网页进度条效果

利用js编写网页进度条效果

网页,进度条,效果,电脑软件,js,一、基本思路为了让我们编写的网页进度条满足现有需求,又足够轻便,所以使用原生js写一个构造函数,为了见名知义,可以把该函数命名为”Loading”。该函数接收2个参数,分别为arr、callback。其中arr定义图片数组,call…

js鼠标跟随运动效果

js鼠标跟随运动效果

鼠标,运动,效果,电脑软件,js,本文实例为大家分享了js鼠标跟随效果展示的具体代码,供大家参考,具体内容如下1、使用命令创建基本结构ul.cursorPlay#cursorPlay>li*12>a>img+div>span2、给span标签添加字段3、设置基本的样式cursorPlay的宽度 9…

如何修改Excel2007自选图形中的文

如何修改Excel2007自选图形中的文

文字,图形,修改,格式,电脑软件,  给Excel2007中的自选图形添加文字,可能有些朋友还不太懂。在Excel中,输入进去的字怎么修改格式,其实这些都有不难。以下是小编为您带来的关于修改Excel2007自选图形中的文字格式,希望对您有所帮助。修改Excel…

excel2007资源不足解决方法excel资

excel2007资源不足解决方法excel资

解决方法,电脑软件,excel,strong,Excel,  在Excel 2007中,对于表格较大的文件,在多次调用的过程中,会出现以下问题&ldquo;可用资源不足,EXCEL无法完成此任务,请少选择一些数据或关闭其他应用程序&rdquo;,今天,小编就教大家如何对资源不足的解决…

Photoshop合成简约大气温馨的家居

Photoshop合成简约大气温馨的家居

家居,简约,大气,海报,温馨,本教程主要使用Photoshop合成简约温馨的家居主题海报,制作主题海报是一项综合工程,首先要对客户的建议进行深入分析,找准思路;然后画出稿图;再搜集所需的素材进行溶图即可。喜欢的朋友让我们一起来学习吧。最终效果画…