在 react 的类组件中,如果我们需要某个点击事件,通常会这样写: onClick={this.changeWeather}
但为了能够使 changeWeather 方法中能够正确找到 this, 我们通常需要在constructor构造器中这样写:this.study = this.study.bind(this)
为了能够比较好地解释清楚这个原理,我们先来回顾一下 es6 的 class:
es6的class类 :
class Person {
// new Person()后,constructor构造器中的属性在实例对象上
constructor(name, age) {
this.name = name
this.age = age
}
// 方法在原型上
speak () {
this.study()
}
// 方法在原型上
study () {
console.log('study', this)
}
}
var p1 = new Person('tom', 18).study
console.log(p1)
p1() // window调用study方法,所以结果为:undefined (类中开启局部严格模式,所以不指向window)
var p2 = new Person('alice', 23)
p2.study() // Person的实例对象调用study方法,所以结果为:Person {name: 'alice', age: 23}
只有通过Person实例对象调用study方法时,this才会指向Person
为了能够使 p1() 也能够通过this找到Person实例对象,就需要在 constructor 添加 this.study = this.study.bind(this):
constructor(name, age) {
this.name = name
this.age = age
// bind(this)中, this指的就是Person实例对象
this.study = this.study.bind(this)
}
构造器中的this指向的是:实例对象
分两步:
1. = 右边相当于先找到原型中的方法study, 然后改变原型中study的this指向(指到实例对象上);
2. = 左边相当于将改变完this指向的函数体给到 属性 study, 使得实例对象上也有study方法。
添加前:Person {name: 'alice', age: 23} -- study 方法在原型上;
添加后:Person {name: 'alice', age: 23, study: ƒ} -- study 方法在Person实例对象
这样,由于实例对象自身有study,就不去原型上去找study方法来,所以此时 var p1 = new Person('tom', 18).study 的study就是改变完this指向的。
react的类组件:
// var VDOM = <div>hello react!</div>
// ReactDOM.render(VDOM, document.getElementById('app'))
// function VDOM () {
// return (
// <div>hello react!!</div>
// )
// }
// ReactDOM.render(<VDOM />, document.getElementById('app'))
class VDOM extends React.Component {
constructor() {
super()
this.state = { isHot: false }
// 将changeWeather方法的this指向VDOM实例(=右边), 并在该实例对象上添加changeWeather方法(=左侧),
this.changeWeather = this.changeWeather.bind(this)
}
render () {
return (
// onClick={this.changeWeather} 代表直接把函数体给了click事件,
// 相当于:var x = new VDOM().changeWeather; x();
<div onClick={this.changeWeather}>{ this.state.isHot ? '1' : '2' }</div>
)
}
changeWeather () {
console.log(33, this)
}
}
ReactDOM.render(<VDOM />, document.getElementById('app'))