react文档demo
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 为了在回调中使用 `this`,这个绑定是必不可少的
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({isToggleOn: !state.isToggleOn }));
}
render() {
return (
<button onClick={this.handleClick}> {this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
在react的类组件中定义事件为什么一定要加bind(this)?习惯于用vue的同学一定会觉得麻烦。这其实涉及到的是类的this的指向问题。
类中的this
类中的this是指向实例的。但方法却不是在实例上而是在原型对象上。下面通过一个简单的类来理解
class Person(){
constructor(name,age){
this.name = name;
this.age = age;
}
study(){
//study方法放在类的原型对象上,供实例的调用,this就是Person的实例
console.log(this);
}
}
const p1 = new Person('张三',18);
// 通过实例调用,即通过原型链上找
p1.study() //Person {name:'张三',age:18}
const p = p1.study
// 直接调用
p() //undefined
study方法却不是在实例上而是在原型对象上。当把p1.study赋值给p来调用的话,就脱离了原型链了,就相当于是在内存里另外定义了一个普通的函数。按理来说this应该是指向window,但类默认开启了局部严格模式,所以指向undefined。
回到react 的demo
<button onClick={this.handleClick}> {this.state.isToggleOn ? 'ON' : 'OFF'}
代码含义为:this指的是实例,实例上没有把handleClick方法就,就从原型链上找,所以实际上就是把原型对象上的handleClick方法赋值给onClick来直接调用。所以this会指向undefined,undefined上没有setState(),所以会报错。
此时this.handleClick是原型上的handleClick的方法
我们想要调用Toggle组件的方法,显然需要让this指向实例,所以就需要用到bind自定义this的指向。
this.handleClick = this.handleClick.bind(this);
bind会新建一个函数并把this指向传入的参数。上面代码含义为根据原型对象上handleClick方法新建一个函数并把this指向实例且把这个新的函数传给实例,作为实例的方法,所以就可以直接调用而不会再往原型链上去找。
此时this.handleClick是实例上的handleClick的方法
ps: 想要让this指向实例,还有一个更简洁的方法,箭头函数 ,运用箭头函数的this指向上一作用域的特性,可以把this指向实例。