React.js 和 ES6:任何不在构造函数中绑定函数的理由

IT技术 javascript reactjs this
2021-04-09 05:14:00

我正在将 React 组件更新到 ES6 并遇到了这个问题中描述的问题 -无法访问事件处理程序内的 React 实例(this) - 即未绑定到组件实例。

这是有道理的,当然有效,但我对答案的另一部分感到困惑:

请注意,绑定一个函数会创建一个新函数。你可以直接在渲染中绑定它,这意味着每次组件渲染时都会创建一个新函数,或者在你的构造函数中绑定它,它只会触发一次。

constructor() {
  this.changeContent = this.changeContent.bind(this);
}

对比

render() {
  return <input onChange={this.changeContent.bind(this)} />;
}

我假设构造函数中的绑定是性能等的首选方法,但您知道他们对假设的看法

这两种方法的权衡是什么?有没有一种情况肯定比另一个好?或者没关系?

3个回答

构造函数中绑定的缺点:react热加载器将不起作用。

render() 中绑定的缺点:性能。


最近我一直在做这个。它比渲染中的绑定稍快,但我愿意用性能来换取灵活性和我梦寐以求的 HMR。

render(){
  return <input onChange={(e) => this.handleChange(e.target.value)}>;
}

例如,它提供了更多的灵活性,并且更容易过渡到规范的 Input 原子。

render(){
  return <input onChange={(x) => this.handleChange(x)}>;
}

或者在你想要的地方添加参数:

render(){
  return (
    <ul>
      {this.props.data.map((x, i) => {
        // contrived example
        return (
          <li 
            onMouseMove={(e) => this.handleMove(i, e.pageX, e.pageY)}>
          {x}
          </li>
        );
      }}
    </ul>
  );
}
我没有在我的项目中使用热加载器,我应该使用它。所有先决条件(webpack 等)都在那里,只是想知道我可以通过热加载器获得哪些主要增强?
2021-06-12 05:14:00
您的第一点足以说服我将其留在 render() 中。如果性能成为问题,我可以随时将其换成生产。
2021-06-17 05:14:00

我认为你所要理解的就是Function.prototype.bind()返回一个新函数。因此,您基本上每次都会通过在render()方法中执行绑定操作来进行创建render()方法被多次调用的可能性非常高。

所以在构造函数中这样做意味着你最终只绑定一次,你可以根据需要多次重复使用它。即使render()多次调用方法,也会使用使用不同绑定上下文创建的相同函数。

是的,理想情况下您应该绑定在构造函数中。让我想起几周前我正在经历一段代码(检查构造函数)。

我认为您已经解决了与重新创建函数有关的主要问题。我想使用箭头函数和属性初始值设定项来突出显示另一个选项。在这种情况下,箭头函数将自动采用本地this.

例如

class MyClass extends React.Component {
  changeComponent = (e) => {
    // this will refer to the component
  }

  render = () => {
    return <input onChange={this.changeContent} />;
  }
}

你可以在这里阅读更多相关信息:http : //babeljs.io/blog/2015/06/07/react-on-es6-plus/

当您有许多想要绑定的函数时,这可能是一个更好的解决方案。但是,您确实失去了仅使用标准函数声明的清洁度。

好吧,这不是有效的 es6,所以......你会得到一个语法错误 :-p 但性能因引擎和这些引擎的版本而异,所以没有正确的答案。
2021-05-23 05:14:00
那些不介意实验性功能的人可以使用它。我见过其他人完全是这样做的。
2021-05-31 05:14:00
当 es6 的原生实现到达浏览器时,这个问题会存在吗?或者这只是从 es6 转换到 es5 时的问题?@FakeRainBrigand
2021-06-01 05:14:00
@FakeRainBrigand 抱歉,您说得对,这是针对财产初始值设定项的计划提案。我已经修改了我的答案以考虑到这一点。可能暂时使此答案完全无法使用,但无论如何我都会将其保留在这里。
2021-06-14 05:14:00
这可能比构造函数中的 .bind 慢,因为它必须为每个实例创建函数,而不仅仅是在同一函数上创建 .bind 。但当然这可能可以忽略不计:-)
2021-06-20 05:14:00