构造器函数 constructor
类式组件里面构造器里面的this是指向实例对象的,这是类的特性
constructor(props) {
super(props);
this.state = {};
this.speak = this.speak.bind(this)
}
- 当组件渲染时,会识别组件的type,如果为类组件,就会创建这个类的一个实例。如果传入了props,那么就把解析出来的props传给这个实例,即:可以在构造函数里使用"this.props",this指向当前类的实例对象
- 可以对state进行初始赋值,不要使用"this.setState()"函数,而应该直接通过 “this.state={}”的方式赋值
- 还可以为事件处理函数绑定实例,“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传递给子组件,可以考虑缓存该函数
另一方面,将方法直接声明在类的实例上,也会丢失原型链共享优势。比如说有这样一个场景:一个封装后的组件,在多个业务模块中进行了多次调用,那么声明在类的原型上的方法只在第一次调用的时候声明,而声明在类的实例上的方法会多次调用,这就造成了内存的多次占用,无谓的消耗了性能。
以上