react中类组件的理解

264 阅读3分钟

构造器函数 constructor

类式组件里面构造器里面的this是指向实例对象的,这是类的特性

constructor(props) {
    super(props);
    this.state = {};
    this.speak = this.speak.bind(this)
  }
  1. 当组件渲染时,会识别组件的type,如果为类组件,就会创建这个类的一个实例。如果传入了props,那么就把解析出来的props传给这个实例,即:可以在构造函数里使用"this.props",this指向当前类的实例对象

  1. 可以对state进行初始赋值,不要使用"this.setState()"函数,而应该直接通过 “this.state={}”的方式赋值
  2. 还可以为事件处理函数绑定实例,“this”指向当前类的实例对象

类组件的this指向

JSX语法中传递的事件不是一个字符串,而是一个函数(如:onClick={this.onOk}),此时onClick即是中间变量,最终是由React调用该函数,而因为开启了严格模式的缘故,this 是undefined,所以处理函数中的this指向会丢失。

而在react中经过了处理,使得在类式组件中有一些地方的this得以指向当前的实例对象 , constructor和render等生命周期钩子

可以看到,顺着原型链向上游找寻,当前实例对象的类Component中存在了上述两种函数

而我们平时开发中,在类组件声明函数时,也是直接声明在类中的,所以就需要我们手动的更改这些函数的this指向,以便更好的调用。

查看官网,可以找到两种更改this的方式,这里将一一列举:

方法一:在构造函数执行时,通过 "bind" 更改this指向

  • 使用 bind 绑定 this 后,不论是哪里调用,该函数里面的 this 都不会变化了
  • 该方法会在实例每次生成的时候,触发,并执行一次 bind()的方法
class LoginItem extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: "lgd467",
    };
    this.onOk = this.onOk.bind(this);
  }
  onOk() {
    console.log(this, "this1111");
  }
  render() {
    return (
      <div>
        <Button onClick={this.onOk} />
        这是登录页面
        {this.props.a}
      </div>
    );
  }
}

this.onOk = this.onOk.bind(this),构造器里面的this默认指向实例对象,实例对象通过原型链在类的原型上找着该函数,通过bind函数将其this指向改为实例对象,并返回一个新的函数,再将这个新的函数给实例,并取名为xxxx

这种方式会将函数声明在类中,在每个实例被new出来的时候会分发下去,这样就可以分享原型上的方法及属性

方法二:用箭头函数的方法

class LoginItem extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: "44",
    };
  }
  onOk = () => {
    console.log(this, "this1111");
  };
  render() {
    return (
      <div>
        <Button onClick={this.onOk}>Default Button</Button>
        这是登录页面
        {this.props.a}
      </div>
    );
  }
}

我们可以看出,通过箭头函数这种方式声明的方法,是直接声明在类的实例中,而不是原型上。这一般没有问题,但是如果将该方法作为props传入子组件,那么在某些情况下,会多次调用该方法而导致这些组件进行额外的渲染,这会导致性能上的不友好,因为浏览器每遇到一个函数就会开辟出一个内存空间,所以react官方也是推荐将一些方法声明后,在构造函数中绑定。如果使用该方式声明函数,且声明的函数还将作为props传递给子组件,可以考虑缓存该函数

另一方面,将方法直接声明在类的实例上,也会丢失原型链共享优势。比如说有这样一个场景:一个封装后的组件,在多个业务模块中进行了多次调用,那么声明在类的原型上的方法只在第一次调用的时候声明,而声明在类的实例上的方法会多次调用,这就造成了内存的多次占用,无谓的消耗了性能。

以上