65.9K
CodeProject 正在变化。 阅读更多。
Home

不要在传递 props 时使用 bind

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2016年7月6日

CPOL

3分钟阅读

viewsIcon

7808

不要在传递 props 时使用 bind

Don't call .bind when passing props

在编写 React 代码时,你经常会想要将一个函数传递给 props。通常,这是为了将回调函数传递给子组件,以便子组件可以通知父组件某个事件的发生。

重要的是要记住函数的 *绑定* – 当它被调用时,它的 this 对象将指向哪里。

有几种方法可以确保绑定正确,有些比其他方法更好。本文将介绍这些选项。

方法 #1:自动绑定(良好,仅适用于 React.createClass)

如果你正在使用 React.createClass,组件中的成员函数会自动绑定到组件实例。你可以自由地将它们传递给其他地方,而无需调用 bind,并且你始终传递完全相同的函数,因此没有性能损失。

var Button = React.createClass({
  handleClick: function() {
    console.log('clickity');
  },
  render: function() {
    return (
      <button onClick={this.handleClick}/>
    );
  }
});

方法 #2:在 render 中调用 .bind(糟糕,ES6)

在使用 ES6 类时,React *不会* 自动绑定组件内部的成员函数。

像这样在最后一刻进行绑定是一种使其正常工作的方法,但它会损害性能,因为每次重新渲染时都会创建一个新函数(这可能会很频繁)。

class Button extends React.Component {
  handleClick() {
    console.log('clickity');
  }

  render() {
    return (
      <button onClick={this.handleClick.bind(this)}/>
    );
  }
}

这是另一个同样糟糕的变体,每次调用 render 时都会创建一个函数

class Button extends React.Component {
  handleClick() {
    console.log('clickity');
  }

  render() {
    var handleClick = this.handleClick.bind(this);
    return (
      <button onClick={handleClick}/>
    );
  }
}

方法 #3:在 render 中使用箭头函数(糟糕,ES6)

与上面的示例类似,只是这个示例使用箭头函数而不是调用 bind。它看起来更好,但它 *仍然* 每次调用 render 时都会创建一个函数!不好。

class Button extends React.Component {
  handleClick() {
    console.log('clickity');
  }

  render() {
    return (
      <button onClick={() => this.handleClick()}/>
    );
  }
}

方法 #4:使用箭头函数的类实例字段(良好,ES8+)

这种方法通过在组件创建时将 handleClick 设置为箭头函数 *一次* 来工作。在 render 和其他函数中,this.handleClick 可以安全地传递,因为箭头函数保留了 this 绑定。

这个方法被标记为“ES8+”,因为它在技术上不属于 ES6 *或* ES7(又名 ES2016)的一部分。ES2016 已完成,并且仅包含 Array.prototype.includes 和指数运算符,因此如果它最终进入规范,它可能会是 ES2017(ES8)或更高版本。

即使 Babel 支持此功能,但仍存在(很小)风险,该功能可能会从规范中删除并需要进行一些重构,但很多人都在使用它,因此它似乎很可能保持不变。

class Button extends React.Component {
  // Use an arrow function here:
  handleClick = () => {
    console.log('clickity');
  }

  render() {
    return (
      <button onClick={this.handleClick}/>
    );
  }
}

方法 #5:在构造函数中绑定(良好,ES6)

你可以在构造函数中设置绑定一次,然后永久使用它们! 别忘了调用 super

class Button extends React.Component {
  constructor(props) {
    super(props);

    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    console.log('clickity');
  }

  render() {
    return (
      <button onClick={this.handleClick}/>
    );
  }
}

方法 #6:使用装饰器(良好,ES8+)

有一个名为 autobind-decorator 的不错的库,可以做到这一点

import autobind from 'autobind-decorator';

class Button extends React.Component {
  @autobind
  handleClick() {
    console.log('clickity');
  }

  render() {
    return (
      <button onClick={this.handleClick}/>
    );
  }
}

@autobind 装饰器绑定 handleClick 方法,一切就绪。 你甚至可以在整个类上使用它,如果你很懒的话

import autobind from 'autobind-decorator';

@autobind
class Button extends React.Component {
  handleClick() {
    console.log('clickity');
  }

  handleOtherStuff() {
    console.log('also bound');
  }

  render() {
    return (
      <button onClick={this.handleClick}/>
    );
  }
}

再次说明,ES2016/ES7 不包含此功能,因此即使 Babel 支持它,你也在承担一些风险,通过在代码中使用它。

总结

这涵盖了绑定传递给 props 的函数的方式。你知道其他方法吗? 有你最喜欢的方法吗? 在评论中告诉我们。

不要在传递 props 时使用 bind 最初由 Dave Ceddia 在 Angularity 上于 2016 年 7 月 05 日发布。

© . All rights reserved.