资讯专栏INFORMATION COLUMN

React 深入系列5:事件处理

willin / 465人阅读

摘要:使用匿名函数先上代码代码点击的事件响应函数是一个匿名函数,这应该是最常见的处理事件响应的方式了。事件响应函数的传参问题事件响应函数默认是会被传入一个事件对象作为参数的。关于事件响应函数,还有一个地方需要注意。

React 深入系列,深入讲解了React中的重点概念、特性和模式等,旨在帮助大家加深对React的理解,以及在项目中更加灵活地使用React。

Web应用中,事件处理是重要的一环,事件处理将用户的操作行为转换为相应的逻辑执行或界面更新。在React中,处理事件响应的方式有多种,本文将详细介绍每一种处理方式的用法、使用场景和优缺点。

使用匿名函数

先上代码:

//代码1
class MyComponent extends React.Component {
  render() {
    return (
      
    );
  }
}

点击Button的事件响应函数是一个匿名函数,这应该是最常见的处理事件响应的方式了。这种方式的好处是,简单直接。哪里需要处理事件响应,就在哪里定义一个匿名函数处理。代码1中的匿名函数使用的是箭头函数,我们也可以不使用箭头函数:

//代码2
class MyComponent extends React.Component {
  render() {
    return (
      
    );
  }
}

虽然代码2的运行效果和代码1相同,但实际项目中很少见到代码2的这种写法。这是因为箭头函数解决了this绑定的问题,可以将函数体内的this绑定到当前对象,而不是运行时调用函数的对象。如果响应函数中需要使用this.state,那么代码2就无法正常运行了。所以项目中一般直接使用箭头函数定义的匿名函数作为事件响应。

使用匿名函数的缺点是:当事件响应逻辑比较复杂时,匿名函数的代码量会很大,会导致render函数变得臃肿,不容易直观地看出组件最终渲染出的元素结构。另外,每次render方法调用时,都会重新创建一个匿名函数对象,带来额外的性能开销,当组件的层级越低时,这种开销就越大,因为任何一个上层组件的变化都可能会触发这个组件的render方法。当然,在大多数情况下,这点性能损失是可以不必在意的。

使用组件方法

代码如下:

//代码3
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {number: 0};
    this.handleClick = this.handleClick.bind(this); // 手动绑定this
  }

  handleClick() {
    this.setState({
      number: ++this.state.number
    });
  }
  
  render() {
    return (
      
{this.state.number}
); } }

点击Button的事件响应函数是组件的方法:handleClick。这种方式的好处是:每次render方法的调用,不会重新创建一个新的事件响应函数,没有额外的性能损失。但是,使用这种方式要在构造函数中为作为事件响应的方法(handleClick),手动绑定this: this.handleClick = this.handleClick.bind(this),这是因为ES6 语法的缘故,ES6 Class 的方法默认不会把this绑定到当前的实例对象上,需要我们手动绑定。每次都手动绑定this是不是有点繁琐?好吧,让我们来看下一种方式。

使用属性初始化语法

使用ES7的属性初始化语法( property initializers ),代码可以这样写:

//代码4
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {number: 0};
  }

  handleClick = () => {
    this.setState({
      number: ++this.state.number
    });
  }
  
  render() {
    return (
      
{this.state.number}
); } }

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

事件响应函数的传参问题

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

使用第一种方式的话很简单,直接使用新参数:

//代码5
class 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 (
      
    {this.state.list.map( (item)=>(
  • this.handleClick(item, event)}>{item}
  • ) )}
); } }

onClick的响应函数中,方法体内可以直接使用新的参数item。

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

//代码6
class 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 (
      
    {this.state.list.map( (item)=>(
  • {item}
  • ) )}
); } }

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

//代码7
class 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 (
      
    {this.state.list.map( (item)=>(
  • {item}
  • ) )}
); } }

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

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

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

下篇预告:

React 深入系列6:高阶组件

我的新书《React进阶之路》已上市,请大家多多支持!
链接:京东 当当

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95197.html

相关文章

  • React 深入系列4:组件的生命周期

    摘要:因为是深入系列文章,本文不会仔细介绍每个生命周期方法的使用,而是会重点讲解在使用组件生命周期时,经常遇到的疑问和错误使用方式。父组件发生更新导致的组件更新,生命周期方法的调用情况同上所述。 文:徐超,《React进阶之路》作者授权发布,转载请注明作者及出处 React 深入系列4:组件的生命周期 React 深入系列,深入讲解了React中的重点概念、特性和模式等,旨在帮助大家加深...

    warnerwu 评论0 收藏0
  • React 深入系列4:组件的生命周期

    摘要:因为是深入系列文章,本文不会仔细介绍每个生命周期方法的使用,而是会重点讲解在使用组件生命周期时,经常遇到的疑问和错误使用方式。父组件发生更新导致的组件更新,生命周期方法的调用情况同上所述。 React 深入系列,深入讲解了React中的重点概念、特性和模式等,旨在帮助大家加深对React的理解,以及在项目中更加灵活地使用React。 组件是构建React应用的基本单位,组件需要具备数据...

    alexnevsky 评论0 收藏0
  • 深入React知识点整理(一)

    摘要:以我自己的理解,函数式编程就是以函数为中心,将大段过程拆成一个个函数,组合嵌套使用。越来越多的迹象表明,函数式编程已经不再是学术界的最爱,开始大踏步地在业界投入实用。也许继面向对象编程之后,函数式编程会成为下一个编程的主流范式。 使用React也满一年了,从刚刚会使用到逐渐探究其底层实现,以便学习几招奇技淫巧从而在自己的代码中使用,写出高效的代码。下面整理一些知识点,算是React看书...

    Gilbertat 评论0 收藏0
  • 王下邀月熊_Chevalier的前端每周清单系列文章索引

    摘要:感谢王下邀月熊分享的前端每周清单,为方便大家阅读,特整理一份索引。王下邀月熊大大也于年月日整理了自己的前端每周清单系列,并以年月为单位进行分类,具体内容看这里前端每周清单年度总结与盘点。 感谢 王下邀月熊_Chevalier 分享的前端每周清单,为方便大家阅读,特整理一份索引。 王下邀月熊大大也于 2018 年 3 月 31 日整理了自己的前端每周清单系列,并以年/月为单位进行分类,具...

    2501207950 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<