反应:推荐使用哪种箭头或常规功能?

时间:2018-08-27 00:05:47

标签: reactjs ecmascript-6 ecmascript-5

当我感到手工功能/对象绑定以及与范围相关的问题令人头疼之后,我开始使用箭头功能,但是非常有意思的是,我开始知道使用正常功能(ES5)比使用箭头功能(ES6)更好。

我对这些功能的理解

React中的正常功能:

  
      
  1. 手动绑定对象/功能,以便在功能内部玩状态或道具并避免与范围相关的问题
  2.   
  3. 总是在构造函数中绑定对象/函数,而不是直接在渲染中绑定
  4.   
  5. 如果在构造函数中执行此操作,则Webpack仅在组件首次呈现时在bundle.js文件中创建一次新的对象/函数
  6.   
  7. 如果直接在渲染中进行操作,则每次组件渲染并重新渲染时,Webpack都会在bundle.js文件中创建一个新的对象/函数
  8.   
  9. 如果您不绑定,则无法访问状态或道具。您必须将当前对象分配给局部变量,否则this.state或this.props未定义
  10.   

React中的箭头功能:

  
      
  1. 无需在构造函数中绑定对象/函数也无需渲染
  2.   
  3. 您无需依赖当前对象的局部变量项,即让它= this;
  4.   
  5. 您将不会遇到范围问题,并且对象/函数绑定会自动出现
  6.   

但是我的询问是,我听说建议使用常规函数并将其绑定到构造函数中,而不要使用箭头函数,因为每次组件渲染和重新渲染时,箭头函数都会在Webpack bundle.js中创建新的对象/函数。

  

这是真的吗?推荐哪个?

此线程接受的答案Correct use of arrow functions in React说—>这取决于您在哪里使用Arrow函数。如果在render方法中使用Arrow函数,那么每次调用render时,它们都会创建一个新实例,就像绑定如何工作一样。

很抱歉,如果您觉得这是一个戏剧问题,但这是我最大的疑问。请建议

2 个答案:

答案 0 :(得分:6)

那里有很多答案,但人们总是感到困惑。我知道这一点是因为我前一段时间感到困惑。一段时间后,我掌握了这些概念。

  
      
  1. 手动绑定对象/功能,以便与状态或道具一起玩   函数内部,并避免与范围相关的问题
  2.   

并非完全正确。您无需绑定功能即可与状态或道具一起玩。当您在合并范围中失去this上下文时,将函数绑定到this。例如在回调函数中。

class App extends React.Component {
  state = {
    name: "foo",
  }
  aFunction() {
    console.log( this.state.name );
  }
  render() {
    return <div>{this.aFunction()}</div>;
  }
}

您不需要绑定函数,因为this指向您的类,并且您不会丢失其上下文。但是,如果您在按钮之类的回调中使用函数,则必须将其绑定:

class App extends React.Component {
  state = {
    name: "foo",
  }
  aFunction() {
    console.log( this.state.name );
  }

  render() {
    return (
      <div>
        <button onClick={this.aFunction}>Click</button>
      </div>
    );
  }
}

这不起作用,因为您丢失了上下文。现在,您需要以某种方式重新获得其上下文?好的,让我们看看如何做到这一点。首先,我想将其绑定到按钮回调中。

<button onClick={this.aFunction.bind(this)}>Click</button>

是的,这可行。但是,它将在每个渲染中重新创建。所以:

  
      
  1. 总是在构造函数中绑定对象/函数,而不是直接在渲染中绑定
  2.   

是的。不要像我上面那样绑定它,而是在您的构造函数中完成它。

  
      
  1. 如果在构造函数中执行此操作,则Webpack仅在组件出现时在bundle.js文件中创建一次新对象/函数   第一次渲染

  2.   
  3. 如果直接在渲染中进行操作,则每次组件渲染时,Webpack都会在bundle.js文件中创建一个新的对象/函数   然后重新渲染

  4.   

您在这里总结了到目前为止我一直在尝试解释的内容。但是,我想Webpack不是这样做的,您的App是。

  
      
  1. 如果您不绑定,则无法访问状态或道具。您必须将当前对象分配给局部变量,否则this.state或   this.props未定义
  2.   

同样,如果您在类范围内使用函数,则不必绑定它。如果在类之外使用此函数(例如按钮回调),则必须将其绑定。这与stateprops不相关。这与使用this有关。

用于绑定的第二个选项是使用常规函数在构造函数中进行绑定,而第三个选项是使用无绑定的箭头函数。

现在,箭头功能。

  

1。无需在构造函数中绑定对象/函数也无需渲染

是的

  
      
  1. 您无需依赖当前对象的局部变量项,即让它= this;
  2.   

是的

  
      
  1. 您将不会遇到范围问题,并且对象/函数绑定会自动出现
  2.   

是的

  

但我的查询是我听说建议使用常规   函数并将其绑定到构造函数中,而不是使用箭头函数   因为箭头函数会在Webpack中创建新的对象/函数   每次您的组件渲染和重新渲染时,bundle.js。

就像每个人所说的那样,这取决于您在哪里使用它们。

render() {
    return (
        <div>
            <button onClick={() => this.aFunction()}>Click</button>
        </div>
    );
}

在这里,它将在每个渲染中重新创建。但是,如果您不需要传递任何参数,则可以通过引用使用它。

render() {
    return (
        <div>
            <button onClick={this.aFunction}>Click</button>
        </div>
    );
}

与上一个相同。因此,如果在渲染方法中看到(),则在每个渲染中都会重新创建此函数。常规或箭头一无所谓。如果您以某种方式调用它,那么您正在重新创建它。这适用于像aFunction.bind(this)这样的渲染中绑定。我在那里看到()

因此,请通过引用使用函数,以避免出现此问题。现在,最大的问题是,当我们需要一些论点时会发生什么?如果使用箭头函数传递参数,请尝试更改逻辑。

但这真的很重要吗?就像@Eric Kim所说的那样,如果您确实需要优化,则是一个问题。这是一个普遍的建议,因为我已经从很多人那里听到过。但就我个人而言,如果要在每个渲染器中重新创建函数,我会尽量避免使用它们。再次,这完全是个人的。

如何更改逻辑?您正在映射具有项的数组并创建 一个按钮。在此按钮中,您正在使用一个将项目名称传递给函数的函数。

{
    items.map( item =>
        <button onClick={() => this.aFunction(item.name)}>Click</button>
    )
}

此功能将在每个渲染器的每个项目中重新创建!因此,更改逻辑,创建一个单独的Item组件并进行映射。通过itemaFunction作为道具。然后在该组件中使用处理程序函数,即可使用您的函数。

const Item = ( props ) => {
    const handleClick = () => props.aFunction( props.item.name );
    return (
        <button onClick={handleClick}>Click</button>
    );
}

在这里,您正在使用带有其引用的onClick处理程序,它将调用您的真实函数。在每个渲染中均不会重新创建任何功能。但是,缺点是,您需要编写一个单独的组件和更多代码。

您通常可以应用此逻辑。也许会有一些你不知道的例子,谁知道。因此,决定权由您决定。

顺便说一句,@ widged在评论中给出的中型帖子是有关此问题的著名讨论。箭头功能真的比常规功能慢吗?是。但是多少钱?我猜没有那么多。同样,对于已编译的代码也是如此。将来,当它们变得原生时,它们将成为更快的。

作为个人说明。自从我喜欢箭头功能以来,我一直都在使用它们。但是不久前在讨论中,有人说

  

当我在课堂上看到箭头功能时,我认为:'此功能   在此类之外被使用/调用”。如果我看到一个普通的我   了解此函数在类内部调用。

我真的很喜欢这种方法,现在,如果不需要在类之外调用函数,我将使用常规方法。

答案 1 :(得分:1)

如果您具有以下React代码,则

class A extends React.Component {
  constructor(props) {
    super(props)
    this.state = {name: props.name}
  }
  render() {
    return (
       <button onclick={(event)=>console.log(this.state.name)} />
    )
  }
}

更改为关注

class A extends React.Component {
  state = {name: this.props.name}
  render() {
    return (
       <button onclick={this.logName} />
    )
  }
  logName = (event) => {
    console.log(this.state.name)
  }
}

这样,您就不会在每个渲染器上都创建新的匿名函数。

每次运行代码时都会创建新的函数实例 ()=>,这不是magic。看看以下成员函数

class A {
  memberFuncWithBinding = () => {}
  memberFuncWithoutBinding(){}
}

实例化类时,这两个成员函数仅创建一次。再说一次,没有魔术,而是上级成员函数是首选,因为在该函数中使用this时,您将具有正确的A类绑定。

编辑:看,在遇到问题之前,请勿尝试优化代码。创建新函数时,每个渲染速度都较慢,但只有毫秒级。