概要
在初次使用React时,经常会遇到this丢失的问题。下面总结几种React中绑定this的方法。
首先看下面的代码:
class Demo extends Component{
constructor(props){
super(props)
}
handleClick(){
console.log('this', this)
}
render(){
return (
<div>
<button onClick={this.handleClick}>点我</button>
</div>
)
}
}
ReactDOM.render(<Demo/>, document.getElementById('test'))
如果之前是使用Vue开发的话,很容易写成这样,但是在react中,这样写,在执行的时候我们就会找不到this的引用。
我们首先要了解,我们在类中定义的handleClick和render方式是定义在类的原型上了。只用类的实例对象才可以调用,且函数内部的this指向实例本身。
在ReactDOM.render()执行的时候,会帮我们new一个实例对象,并调用render方法,所以在render方法内部的this指向实例自身。但是<button onClick={this.handleClick}>点我</button>这里绑定的事件处理函数为this.handleClick方法的引用。但是当我们点击的时候,handleClick的执行上下文为Window,由于jsx经babel编译后会开启严格模式。所以this指向变为undefined。
1. 在构造函数中使用bind改变this的指向
class Demo extends Component{
constructor(props){
super(props)
// 该方法会定义在实例对象上。
this.handleClick = this.handleClick.bind(this)
}
handleClick(){
console.log('this', this)
}
render(){
return (
<div>
<button onClick={this.handleClick}>点我</button>
</div>
)
}
}
ReactDOM.render(<Demo/>, document.getElementById('test'))
这种处理方案是我们在constructor中为每一个实例添加一个方法且this绑定为自身。
此时onClick绑定的处理函数,就不是实例原型链上的函数了,而是在constructor中为实例自身添加的方法。
我们来看下面的代码
class Demo extends Component{
handleClick(){
console.log('this', this)
}
render(){
return (
<div>
<button onClick={this.handleClick(e)}>点我</button>
</div>
)
}
}
ReactDOM.render(<Demo/>, document.getElementById('test'))
假如我们需要传递参数,我们可能会发现,事件并没有绑定成功。
我们仔细看,就会发现,这里我们将handleClick方法的返回值undefined绑定为onClick的处理函数。(与Vue的模板解析不同,这里是按js的语法)
我们可以使用下面这种方案。
2. 使用箭头函数绑定事件
class Demo extends Component{
handleClick(){
console.log('this', this)
}
render(){
return (
<div>
<button onClick={(e) => this.handleClick(e)}>点我</button>
</div>
)
}
}
ReactDOM.render(<Demo/>, document.getElementById('test'))
我们知道,render函数的this指向为实例自身,所以,我们可以直接在绑定的时候使用箭头函数,此时handleClick的执行上下文为箭头函数定义时的作用域。
3. 使用箭头函数定义实例方法
class Demo extends Component{
// 该方法定义在实例对象,且执行上下文为实例自身
handleClick = ()=>{
console.log('this', this)
}
render(){
return (
<div>
<button onClick={this.handleClick}>点我</button>
</div>
)
}
}
ReactDOM.render(<Demo/>, document.getElementById('test'))
这种方案是直接将方法定义在自身上,且通过箭头函数将this指向实例自身。