class类中this绑定
类的方法内部如果含有this,默认指向类的实例,但是一些场景下使用,会导致this的指向偏离预期,所以需要绑定定义时候的this,也就是实例对象
如下
<!--html-->
<button id="btn">click</button>
<!--js-->
const btn = document.getElementById('btn');
class CheckThis {
constructor(ele) {
this.ele = ele;
this.count = 0;
this.ele.addEventListener('click', this.click);
}
click() {
console.log(this); // DOM
this.count++;
console.log(this.count); // NaN
}
}
const thisInstance = new CheckThis(btn);
在这里click方法中的this指的是dom节点而不是实例对象,
因为addEventListener()将this的指针设置为冒泡事件的DOM元素
相当于
var m = this.click;
this.ele.addEventListener('click', m) //此时m函数中this的指向创建事件的元素
再看一个例子
import React, { PureComponent } from 'react';
class Index extends PureComponent {
testHandle(){
console.log(this); // undefined
};
reder(){
return (
<Button onClick={this.testHandle}>click</Button>
)
}
}
React事件为合成事件,class并不会为方法自动绑定this到当前对象上,再由于class 内部是严格模式,所以 this 实际指向的是undefined,为避免这种this指向问题有几种方法来解决这种问题
1.使用箭头函数
直接在React元素中采用箭头函数
1 | import React, { PureComponent } from 'react'; |
因为箭头函数中的this指向的是函数定义的对象,所以可以保证this总是指向当前组件的实例对象
优化点:直接在render方法中为元素事件定义事件的处理函数,每次render调用时,都会创建一个新的事件处理函数,带来额外的性能开销
2.组件方法
直接将组件的方法赋值给元素的事件属性,同时在类的构造函数中,将这个方法的this绑定到当前对象。
1 | import React, { PureComponent } from 'react'; |
这种方式的好处是每次render不会重新创建一个回调函数,没有额外的性能损失。但在构造函数中,为事件处理函数绑定this, 尤其是存在多个事件处理函数需要绑定时,这种模板式的代码还是会显得烦琐。而且对于函数传递参数来说不太方便
1 | import React, { PureComponent } from 'react'; |
这种方式依然存在每次render都会创建一个函数的问题,但在需要为处理传递额外参数提供便利
3.属性初始化语法
使用ES 7的property initializers会自动为class中定义的方法绑定this
1 | import React, { PureComponent } from 'react'; |
这种方式既不需要在构造函数中手动绑定this, 也不需要担心组件重复渲染导致的函数重复创建问题。但是, property initializers这个特性还处于试验阶段, 默认是不支持的,不过, 使用官方脚手架Create React App创建的项目默认是支持这个特性的。你也可以自行在项目中引入babel的transform-class-properties插件获取这个特性支持。
参考资料
引用 React+进阶之路