React 基础小知识:this

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

二倍速刷 B 站 # 尚硅谷2021版React技术全家桶 视频,记录一下有趣的一些点吧。(习惯看文章和看文档,现刷视频感觉有点不适应,单口相声老师讲的很好,讲的太细但也不错。)

React 类式组件中的 this

先来看一个 React 类式组件:

class Weather extends React.Component {
  constructor(props) {
    super(props)
    this.state = {isHot: true}
    this.changeWeather = this.changeWeather.bind(this)
  }
  render() {
    const { isHot } = this.state
    return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'}</h1>
  }
  changeWeather() {
    console.log(this)
  }
}
ReactDOM.render(<Weather/>, document.getElementById('test'))
复制代码

附:ReactDOM.render 方法负责解析找到类,然后 new 出该类的组件实例,并调用其 render 方法。

构造方法中 this.state 哪里来的?

由代码可知 Weather 类继承于 React.Component,在 constructor 方法中打印 this (下图)可以看到 state: null ,说明 state 属性在 React.Component 中的 constructor 方法中已经被定义且初始化赋值为 null。同样 React 初始化的核心属性还有:context、props、refs...

截屏2021-09-27 下午3.59.52.png

因此我们可以直接在 Weather 类的构造方法里面,使用 this 去访问 state 并且给它赋值。

render 方法中 this.state 解构赋值?

按照 ES6 语法规则 render 方法定义是为实例方法,挂载在 Weather 原型上。

截屏2021-09-27 下午7.41.09.png

因为 render 方法是由 Weather 类组件实例调用的,所以它的 this 就是 Weather 组件实例,因此可以进行解构赋值,然后访问到该实例构造方法中定义的实例属性值为 isHot: true

JSX 中的事件绑定 onClick={this.changeWeather}

render 方法里面返回了 JSX:return <h1 onClick={this.changeWeather}></h1>。有没有想过,为什么不是 return <h1 onClick={changeWeather}></h1>?为什么需要 this 去访问?

这个问题很简单,其实是类的基础知识,changeWeather 方法是 Weather 类的实例方法,因此要通过 this 的方式去调用。

通过 JSX 事件绑定调用的 changeWeather 方法中的 this

当我们注释掉构造方法中的 this.changeWeather = this.changeWeather.bind(this) 然后点击触发 changeWeather 方法,发现控制台打印出来的 thisundefined。这是为什么呢?明明在 render 方法里面打印的 this 是当前实例。

截屏2021-09-27 下午7.57.21.png

这个属于 this 绑定中的隐式丢失,那什么是 this 的隐式丢失

let obj = {
  a: 42,
  foo: function() {
    console.log(this.a);
  }
};

// 函数别名
let bar = obj.foo; 

obj.foo(); // 42
bar(); // undefined
复制代码

最常见的就是这种函数别名导致的隐式丢失bar() 相当于 window 调用 foowindow 中没有 a 变量,就会返回 window,那为什么上面返回 undefined 呢?其实是在严格模式下会返回 undefined。(而上面 React 案例中返回 undefined 也是因为 Babel 转换在方法内开启了严格模式。)

JSX 代码中 <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'}</h1>this.changeWeather 只是通过类的实例对象沿着原型链找到了 changeWeather 方法并交给 onClick 作为回调,此时没有调用这个方法。等真正点击的时候,只是从堆里面把方法拿出来执行。

截屏2021-09-27 下午8.17.25.png

因此我们需要在构造函数的时候将 this 进行硬绑定:this.changeWeather = this.changeWeather.bind(this)。从右到左分析这个代码,右边的 this.changeWeather 是原型链上,使用 bind 绑定当前实例然后返回一个新函数,并赋值给 this.changeWeather 挂在实例自身的 changeWeather 上。

猜你喜欢

转载自juejin.im/post/7013528637454417956