06-react里面的this指向问题

5 篇文章 0 订阅

函数中使用this

在函数中使用this的时候,我们经常用箭头函数声明。或者使用bind来修改this的指向。但是这究竟是为什么呢?
下面我们来看看直接在函数中直接使用会出现什么问题吧

在函数中直接使用this的问题

import React, { Component } from 'react';

export default class App extends Component {
  state= {
    name: '张三'
  }
  handleClick (){
      console.log(this);
      this.setState({name:'李四'})
  }
  render() {
   
    return (
      <div>
        <h1>我的名字是{this.state.name}</h1>
        <button onClick={this.handleClick}>点击我改名字</button>
      </div>
    );
  }
}

在这里插入图片描述
很简单的例子,一个name状态 。点击按钮后,修改函数的状态。感觉没问题,但是当点击之后会报一个错误。
在这里插入图片描述
this是undefined,自然就不能调用setState方法了。这是为什么呢?
因为handleClick方法并不是实例后对象调用的,而是直接调用的。它不同于render()方法和生命周期函数。这些函数是类主键实例后自动调用的,是实例化的对象调用的。而handleClick是我们自己声明的函数。它作为回调函数给了click事件,所以当类实例化之后,它并没有触发。后来当触发单击事件后,仅仅是作为一个函数调用。并没有通过实例调用,所以this就是undefined。
我们可以在render中打印一下this
在这里插入图片描述可以发现函数定义到了类的原型上面,所以只能通过实例对象调用才能生效。

解决方法一 通过箭头函数

声明函数的时候使用箭头函数声明,因为箭头函数没有自己的this。它的this取决于父级的this指向。

import React, { Component } from 'react';

export default class App extends Component {
  state= {
    name: '张三'
  }
  handleClick = () => {
      console.log(this);
      this.setState({name:'李四'})
  }
  render() {
    
    return (
      <div>
        <h1>我的名字是{this.state.name}</h1>
        <button onClick={this.handleClick}>点击我改名字</button>
      </div>
    );
  }
}

this的值就不再是undefined了,而且可以看出来函数被定义到了,类实例化本身上,而不是原型上
在这里插入图片描述

方法二 利用bind()方法

import React, { Component } from 'react';

export default class App extends Component {
  constructor(props){
    super(props);
    this.state= {
      name: '张三'
    }
    this.handleClick = this.handleClick.bind(this); //这里是主要变化,右边的handleClick是原型上面的方法,左边的是类本身
  }
  handleClick ()  {
      console.log(this);
      this.setState({name:'李四'})
  }
  render() {
    return (
      <div>
        <h1>我的名字是{this.state.name}</h1>
        <button onClick={this.handleClick}>点击我改名字</button>
      </div>
    );
  }
}

我们可以看一下this
在这里插入图片描述
this.handleClick = this.handleClick.bind(this);
就是在类本身上也添加了一个handleClick方法,bind()可以改变this的指向并且返回一个函数。
把改变this的方法赋值给类的同名方法handleClick,下面单击事件触发的就是类本身的方法。

通过原生js演示问题

class Car {
  name = '奔驰';
  run(){
    console.log(this.name+'在奔跑');
  }
}
const c = new Car();
c.run()

能够正常执行,输出结果。因为现在是使用实例调用的方法
在这里插入图片描述

class Car {
  name = '奔驰';
  run(){
    console.log(this.name+'在奔跑');
  }
}
const c = new Car();
c.run()
const fun = c.run;
fun()

不能正常执行,因为函数是被直接调用的。所以this为undefined
在这里插入图片描述
利用bind()改变this的指向,并且赋值给类实例本身。

class Car {
  name = '奔驰';
  constructor(){
    this.run = this.run.bind(this)//这里右边的run方法是原型上的方法,左边的run是类本身的
  }
  run=()=>{
    console.log(this.name+'在奔跑');
  }
  
}
const c = new Car();
c.run()
const fun = c.run;

bind方法的使用

class Car {
  name = '奔驰';
  run(){
    console.log(this.name+'在奔跑');
  }
}
const c = new Car();
c.run()
const fun = c.run;
fun.bind(Car)

利用箭头函数,方法也会被定义到类的实例上

class Car {
  name = '奔驰';
  run=()=>{
    console.log(this.name+'在奔跑');
  }
}
const c = new Car();
c.run()
const fun = c.run;
fun()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值