改变react组件中方法的指向
在react的class中(一般用class作为构造函数的语法糖),我们经常会遇到引用方法的情况,比如下面这个demo:
- 他的效果是,当我点击按钮,控制台输出’这个是信息’
class App extends React.Component {
constructor(){
super()
this.state = {
}
}
render(){
return(
<div>
<button onClick={
this.showMsg}>按钮</button>
</div>
)
}
showMsg(){
console.log('这个是信息');
}
}
但是,当我们要使用showMsg()
这个方法中的this时,这个this指的是什么呢?
- 尝试一下,结果打印的是undefined
那么问题来了,如何将上面showMsg()
这个方法的this指向App这个对象,而不是undefined呢?
有四种方法可以将方法中的this指向它所在的组件对象
第一种,简单暴力,直接使用api bind改变this的指向
- 使用
bind()
api来改变showMsg
的this,下面的事件中,两个this都是方法所在的组件对象 - 因此将showMsg原本的this改成了render函数的this,即App这个组件对象
- 但是当我们有很多按钮时,这么写每个事件都需要改变一次this,太麻烦了,有没有其他办法呢?
<button onClick={
this.showMsg.bind(this)}>改变showMsg指向的第一种方法</button>
- 下面的代码,每次都要手动绑定一次,虽然可以实现需求,但是太麻烦了
render(){
return(
<div>
<button onClick={
this.showMsg}>按钮</button>
<button onClick={
this.showMsg.bind(this)}>改变showMsg指向的第一种方法</button>
<button onClick={
this.showMsg.bind(this)}>改变showMsg指向的第一种方法</button>
<button onClick={
this.showMsg.bind(this)}>改变showMsg指向的第一种方法</button>
<button onClick={
this.showMsg.bind(this)}>改变showMsg指向的第一种方法</button>
<button onClick={
this.showMsg.bind(this)}>改变showMsg指向的第一种方法</button>
</div>
)
第二种,在第一种的基础上,将重复的代码合成一个
- 原理,既然我每次都要改变一次
showMsg
this的指向,那么我能不能只写一次就改变他原本的this指向呢? - 下面是实现的代码,使用
this.showMsg = this.showMsg.bind(this)
,直接将showMsg原本的this指向了组件对象
class App extends React.Component {
constructor(){
super()
this.state = {
}
this.showMsg = this.showMsg.bind(this)
}
render(){
return(
<div>
<button onClick={
this.showMsg}>按钮</button>
<button onClick={
this.showMsg}>改变showMsg指向的第二种方法</button>
<button onClick={
this.showMsg}>改变showMsg指向的第二种方法</button>
<button onClick={
this.showMsg}>改变showMsg指向的第二种方法</button>
<button onClick={
this.showMsg}>改变showMsg指向的第二种方法</button>
</div>
)
}
showMsg(){
console.log(this);
}
}
第三种方法,既然showMsg
本身的this指向的undefined,那么如果他本身没有this,那他的 this就会寻找它上级的作用域的对象
- 所以我们可以使用箭头函数,箭头函数本身不绑定this,因此
showMsg
中的this只会向showMsg
的上级作用域寻找对象,而showMsg
上级作用域的对象就是组件对象. - 使用到了es6的特性
- 下面是代码,可以看到依然是成功的
class App extends React.Component {
constructor(){
super()
this.state = {
}
}
render(){
return(
<div>
<button onClick={
this.showMsg}>按钮</button>
<button onClick={
this.showMsg}>改变showMsg指向的第三种方法</button>
</div>
)
}
showMsg=()=>{
console.log(this);
}
}
第四种方法,最推荐的方法,也是应该牢记经常使用的方法
- 上次的博客记过,
onClick
后面的{}
符号可以做很多事情,可以加减乘除,可以放方法,可以各种运算,那么可以现在{}
中放一个方法
<button onClick={
()=>{
console.log(this)}}>改变showMsg指向的第四种方法</button>
- 这个时候可以看到,点击按钮,打印出来的this就是组件对象本身
- 所以可以看做是
onclick=()=>{
console.log(this)
}
- 那么替换一下,就可以写成下面这个样子
- 当我点击按钮时,我执行箭头函数,而箭头函数中的
showMsg
方法会被执行 - 还是利用到了箭头函数的tis指向,箭头函数不绑定this
- 而且上面写了打印箭头函数this的例子,所以
this.showMsg()
中的this指向的是组件对象
<button onClick={
()=>{
this.showMsg()}}>改变showMsg指向的第四种方法</button>
总结
就是这么理解
let x = {
a(){
console.log(this)
}
}
x.a()//this指向x
let b = x.a//函数a变成了b,b的指向是window,react中指代onClick,指向undefined,已经不是原来那个a了
b()//输出的是window
let c = ()=>{
x.a()}//引用原来那个a
c()//输出的是x