传递箭头函数 vs 传递函数

IT技术 javascript reactjs arrow-functions
2021-04-17 04:11:35

说我有一个功能:

handleChange = (e) => {
  this.setState({ [e.target.id]: e.target.value });
}

以下有什么区别:

1.

<FormControl value={this.state.password} onChange={this.handleChange} />
<FormControl value={this.state.password} onChange={(e) => this.handleChange(e)} />
6个回答

第二种情况 ananonymous function被创建,它执行该handleChange方法并从而为其提供context.

每次 React 组件渲染时,都会在第二种情况下创建一个新函数,而不是在第一种情况下,因为向处理程序提供了相同的 handleChange 方法引用。

你可能还想看看渲染中的箭头函数是如何实现上下文绑定的

假设您的事件处理程序在您的class中是这样编写的

handleChange = (e) => {
  this.setState({ [e.target.id]: e.target.value });
}

让我们来看你提到的第一个例子。

<FormControl value={this.state.password} onChange={this.handleChange} />

在这里,对于每次更改,您都在传递 handleChange 函数的内存引用,并且正在向它传递事件对象。

转到第二种方法。

<FormControl value={this.state.password} onChange={(e) => this.handleChange(e)} />

在这里,您将创建一个新的匿名函数,每次发生事件更改时,该函数都将事件对象作为参数。如果您有大型列表项,这会大大增加垃圾收集。在这种情况下添加箭头函数是多余的,因为由于您handleChange最初编写方法的方式,上下文已经绑定作为性能提示,如果您在类中使用箭头函数,请对事件处理程序使用选项 1。

在渲染中使用箭头函数可能会导致一些性能问题。

我建议您在类属性中使用箭头函数,但您必须使用第 2 阶段功能。

在这里你会发现选项之间的一个很好的比较:

https://medium.freecodecamp.org/react-binding-patterns-5-approaches-for-handling-this-92c651b5af56

欢迎提供指向解决方案的链接,但请确保您的答案在没有它的情况下也有用:在链接周围添加上下文,以便您的其他用户了解它是什么以及它为什么在那里,然后引用您页面中最相关的部分“重新链接,以防目标页面不可用。仅是链接的答案可能会被删除。
2021-06-20 04:11:35

在第一种情况下,您使用的handleChange是事件处理程序。

在第二种情况下,您使用一个新函数作为事件处理程序,它依次调用handleChange.

不同的是在第二个例子中会有两个函数调用。否则它们是相同的。

换句话说:不需要使用第二种形式,它甚至可能不利于重新渲染。

第二种方法创建一个包装函数,调用handleChange.
2021-05-28 04:11:35
第二种情况在很多情况下都很有用,甚至在 react 的官方指南中也有使用,在这里没有用,但该模式很有用
2021-06-02 04:11:35
好点子。我只专注于函数的执行。
2021-06-03 04:11:35
@MarcellMonteiroCruz:当然,我只是在谈论 OP 的情况。
2021-06-09 04:11:35
第二个示例在每次渲染时创建一个新函数,对吗?
2021-06-12 04:11:35

我们可以在类构造函数中绑定我们的事件处理程序:

我们现在可以在事件句柄中访问它

class MyClass extends Component {
  constructor(props) {
    super(props)
    this.handleChange = this.handleChange.bind(this)
  }
  handleChange(){
   //you can now access "this" inside handlechange
  } 

}

看起来不错。当我们向类中添加更多事件处理程序时,代码应类似于以下内容:

import React, { Component } from 'react'
import { MyInput, MyAnotherInput } from 'myInputs'

class MyComponent extends Component {
  constructor(props) {
    super(props)
    this.handleChange = this.handleChange.bind(this)
    this.handleClick = this.handleClick.bind(this)
    this.handleKeyPress = this.handleKeyPress.bind(this)
  }

  handleChange(e) {
    e.preventDefault()
  }

  handleClick(e) {
    e.preventDefault()
  }

  handleKeyPress(e) {
    e.preventDefault()

    if (e.nativeEvent.keyCode === 13) {
      console.log('This is enter!')
    }
  }

  render() {
    return (
      <div>
        <MyInput
          onChange={ this.handleChange }
          onClick={ this.handleClick }
          onKeyPress={ this.handleKeyPress }
        />
        <MyAnotherInput
          onChange={ this.handleChange }
          onClick={ this.handleClick }
          onKeyPress={ this.handleKeyPress }
        />
      </div>  
    )
  }
}

这就是我们可以用 es2015 作为预设配置的 Babel 编译器做的事情。

带有箭头函数的事件处理程序

您可能已经看到,当我们创建事件处理程序方法时,我们总是需要将 this 添加到构造函数中,以绑定 this。挺累的。老实说,仅仅为了绑定你的方法而创建构造函数方法是没有意义的。应该有另一种解决方案,而且确实存在。

您只需要安装 stage-1 Babel 预设并使用箭头功能。如果你不知道,怎么做,去 Babel 文档,非常好。

在我们的例子中,我们可以这样写,而不是将方法绑定到 this:

render() {
   return(<MyInput onChange={ (e) => this.handleOnChange(e) } />)
}

我们创建了新的匿名函数,它会自动绑定 this,这就是为什么我们不需要使用 .bind() 方法。我们在类中仍然有相同的方法,并且新的箭头函数作为回调属性中的包装器。

这仍然不是完美的解决方案,因为我们需要更新箭头函数包装器中的参数,并且每次触发渲染方法时我们都会创建新实例。React 属性中的箭头函数也不是一个好主意。