返回

this在React组件中的正确用法及常见问题解析

前端

在初次使用React时,经常会遇到this丢失的问题。下面总结几种React中绑定this的方法。

首先看下面的代码:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  handleClick() {
    // this 指向 MyComponent 的实例
    console.log(this.state.count);
  }

  render() {
    // this 指向 MyComponent 的实例
    return (
      <div>
        <button onClick={this.handleClick}>+</button>
      </div>
    );
  }
}

如果之前是使用Vue开发的话,很容易写成这样,但是在react中,这样写,

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  handleClick = () => {
    // this 指向 MyComponent 的实例
    console.log(this.state.count);
  }

  render() {
    // this 指向 MyComponent 的实例
    return (
      <div>
        <button onClick={this.handleClick}>+</button>
      </div>
    );
  }
}

render函数中this.handleClick实际上是一个箭头函数,其定义方式为() => {}。箭头函数没有自己的this,因此它将使用外层作用域中的this。在上面的示例中,外层作用域是MyComponent类的实例,因此this.handleClick中的this将指向MyComponent类的实例。

另一种绑定this的方法是使用bind()方法。bind()方法可以将一个函数绑定到一个对象,这样当调用该函数时,this将指向该对象。

例如,下面的代码使用bind()方法将handleClick函数绑定到MyComponent类的实例:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  handleClick() {
    // this 指向 MyComponent 的实例
    console.log(this.state.count);
  }

  render() {
    // this 指向 MyComponent 的实例
    return (
      <div>
        <button onClick={this.handleClick.bind(this)}>+</button>
      </div>
    );
  }
}

bind()方法的第一个参数是this,第二个参数是参数列表。在上面的示例中,我们使用this.handleClick.bind(this)将handleClick函数绑定到MyComponent类的实例。

也可以在构造函数中使用bind()方法来绑定this。例如,下面的代码在构造函数中使用bind()方法将handleClick函数绑定到MyComponent类的实例:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    // this 指向 MyComponent 的实例
    console.log(this.state.count);
  }

  render() {
    // this 指向 MyComponent 的实例
    return (
      <div>
        <button onClick={this.handleClick}>+</button>
      </div>
    );
  }
}

在上面的示例中,我们在构造函数中使用this.handleClick = this.handleClick.bind(this);将handleClick函数绑定到MyComponent类的实例。

ES6 类也提供了一种绑定this的方法,称为箭头函数。箭头函数的定义方式为() => {}。箭头函数没有自己的this,因此它将使用外层作用域中的this。

例如,下面的代码使用箭头函数来绑定this:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  handleClick = () => {
    // this 指向 MyComponent 的实例
    console.log(this.state.count);
  }

  render() {
    // this 指向 MyComponent 的实例
    return (
      <div>
        <button onClick={this.handleClick}>+</button>
      </div>
    );
  }
}

在上面的示例中,我们使用handleClick = () => {}将handleClick函数绑定到MyComponent类的实例。

高阶组件也是一种绑定this的方法。高阶组件是一个函数,它接受一个组件作为参数,并返回一个新的组件。新组件具有与原始组件相同的功能,但还具有其他功能,例如绑定this。

例如,下面的代码是一个高阶组件,它将this绑定到组件:

const withThis = (Component) => {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        count: 0
      };
    }

    handleClick() {
      // this 指向 Component 的实例
      console.log(this.state.count);
    }

    render() {
      // this 指向 Component 的实例
      return (
        <Component
          {...this.props}
          handleClick={this.handleClick}
        />
      );
    }
  };
};

我们可以使用withThis高阶组件来绑定this,例如:

const MyComponent = (props) => {
  return (
    <div>
      <button onClick={props.handleClick}>+</button>
    </div>
  );
};

const MyComponentWithThis = withThis(MyComponent);

class App extends React.Component {
  render() {
    return (
      <MyComponentWithThis />
    );
  }
}

在上面的示例中,我们使用withThis高阶组件将this绑定到MyComponent组件。

代理也是一种绑定this的方法。代理是一个对象,它可以将this指向另一个对象。

例如,下面的代码是一个代理对象,它将this指向MyComponent类的实例:

const proxy = new Proxy({}, {
  get: function(target, prop) {
    return this.state[prop];
  },
  set: function(target, prop, value) {
    this.state[prop] = value;
  }
});

我们可以使用代理对象来绑定this,例如:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  handleClick() {
    // this 指向 proxy 对象
    console.log(this.state.count);
  }

  render() {
    // this 指向 MyComponent 的实例
    return (
      <div>
        <button onClick={proxy.handleClick.bind(this)}>+</button>
      </div>
    );
  }
}

在上面的示例中,我们使用代理对象将this绑定到MyComponent类的实例。