【问题标题】:Passing an arrow function vs passing the function传递箭头函数与传递函数
【发布时间】:2018-06-26 13:48:17
【问题描述】:

假设我有一个函数:

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)} />

【问题讨论】:

  • 所以,据我了解,'this' 的问题是通过在handleChange 的声明中使用箭头函数来解决的,因此不需要添加匿名函数。这是正确的吗?

标签: javascript reactjs arrow-functions


【解决方案1】:

在第二种情况下,anonymous function 被创建,它执行handleChange 方法,从而为它提供context

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

您可能还想查看 how arrow function in render achieve context binding

【讨论】:

    【解决方案2】:

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

    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。

    【讨论】:

      【解决方案3】:

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

      我建议你在类属性中使用箭头函数,但你必须使用第二阶段的特性。

      您可以在这里找到选项之间的一个很好的比较:

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

      【讨论】:

      【解决方案4】:

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

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

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

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

      【讨论】:

      • 第二个例子在每次渲染时都会创建一个新函数,对吧?
      • 好点。我只关注函数的执行。
      • 第二种方法创建一个调用handleChange的包装函数。
      • 第二种情况在很多情况下都有用,甚至在react的官方指南中也有使用,在这里没用,但是这种模式很有用
      • @MarcellMonteiroCruz:当然,我只是在谈论 OP 的情况。
      【解决方案5】:

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

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

      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 文档,很好。

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

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

      我们创建了新的匿名函数,它会自动绑定 this, 这就是我们不需要使用 .bind() 方法的原因。我们还是一样 类中的方法,以及新的箭头函数作为回调中的包装器 属性。

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

      【讨论】:

        【解决方案6】:

        在 JavaScript 中处理事件时,开箱即用的 this 上下文可能会非常混乱,您可以在此 excellent writeupread more 了解它。

        回到你的问题,第一种方式onChange={this.handleChange} 不保证handleChange() 中的this 上下文总是相同的组件实例,在许多情况下,this 将引用FormControl 实例发出 onChange 事件。

        第二种方式使用箭头语法,它可以保证this 始终是处理事件的 React 组件实例。

        简而言之,在 React 组件类中首选使用箭头语法进行事件处理,因为它保证了一致的 this 上下文。

        【讨论】:

        • 他们都使用箭头函数
        • handleChange 已经定义为 this 是固定的。
        猜你喜欢
        • 2015-01-25
        • 1970-01-01
        • 1970-01-01
        • 2018-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-21
        • 2023-03-03
        相关资源
        最近更新 更多