JavaScript: Class

20th August 2020 at 2:19pm
JavaScript

Class 是在 ES6 (ECMAScript 2015) 推出的新特性。

在 React 中用 class component 时经常会出现一个问题,即 class 中的 method 默认是非 bound 的。React 的 文档 详细描述了这个问题。

表现在于,如果你想在 method 体中用 this 指代对象的实例时会报错:

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};
  }

  handleClick() {
    // ERROR: this.setState will throw exception
    this.setState(state => ({
      isToggleOn: !state.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

有几个解决方法:

  • 在构建函数中 bind 上(推荐):
    constructor(props) {
      super(props);
      this.state = {isToggleOn: true};
        
      // This binding is necessary to make `this` work in the callback
      this.handleClick = this.handleClick.bind(this);
    }
  • 用仍在实验状态的 public class fields syntax。这个语法有点迷惑性:
    class Toggle extends React.Component {
      // This syntax ensures `this` is bound within handleClick.
      // Warning: this is *experimental* syntax.
      handleClick = () => {
        console.log('this is:', this);
      }
        
      // ...
    }
  • 不直接将 method 赋值给 onClick 属性,而是包裹一个匿名函数:
    class LoggingButton extends React.Component {
      handleClick() {
        console.log('this is:', this);
      }
    
      render() {
        // This syntax ensures `this` is bound within handleClick
        return (
          <button onClick={(e) => this.handleClick(e)}>
            Click me
          </button>
        );
      }
    }