概要
在初次使用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
指向实例自身。