React 组件指定 this 的原因及方式

在使用 React 做组件开发的时候经常需要对某些方法指定 this ,那么为什么需要指定 this 呢、有哪些方式来指定呢、这些方式有什么不同以及性能的优劣的?

一、为什么需要指定this

原因就是 this 丢失!!!

那么好端端的为什么会出现 this 丢失的情况呢?这是因为 react 造成的么

this 丢失是 js 中常见的现象,跟 react 并没有直接关系(有一点点的间接关系)

那么 js 中有哪些常见的 this 丢失的现象呢,举个栗子

const color = 'pink'
const person = {
  color: 'red',
  getColor() {
      return this.color
  }
}
const getColor = person.getColor
console.log(getColor())
复制代码

那么现在打印出来的是什么?没错就是 undefined

认为应该打印 red 或者 pink 的小伙伴需要补充一些 this 指向和 ES6 的相关知识

react 中 this 丢失的原因跟这个基本是一样的,看一段简单的 react 代码

export default class Header extends PureComponent {
    constructor() {
        super()
        this.state = {}
    }
    
    click() {
        console.log(this)
    }
    
    render() {
        return (
            <button onClick={this.click}>ClickPaas</button>
        )
    }
}
复制代码

那么现在打印出来的是什么?没错还是 undefined

这段代码中 button 的点击事件绑定的 click 方法没有手动的指定 this,所以打印出来的 this 为 undefined

前面我们说过,需要手动指定的原因是 this 丢失了,那么 react 组件中的 this 是怎么丢失的呢,这就跟 JSX 语法的解析有关了

React 组件能够显示在页面上形成真实的 dom 节点需要一系列复杂的操作,其中有一步是使用 transform-react-jsx 插件将 JSX 语法转化成多个参数,传递给 react 的 createElement 方法。这些参数可以分为三种类型存储为这样的结构

{
    tag: "button",    // 外层标签的名称或者是自定义组件的名称
    props: { onClick: this.click},  // 外层标签的属性,className id  以及各种鼠标事件,或者是自定义组件含有的自定义属性
    children: ["ClickPaas"]  // 子级节点,
}
复制代码

现在可以看到 Header 组件中的 button 标签上面的属性以及属性值存储的方式了,由此可以明白当 button 标签的 click 事件触发时候相当于执行的是 props.onClick() 所以 this 丢失了

二、有哪些指定 this 的方式呢?
  1. 在构造函数中使用 bind 方法

     constructor() {
         super()
         this.click = this.click.bind(this)
     }
    复制代码

原理:通过 js 提供的 bind 方法改变 this 指向

优势:只需在类组件初始化时指定一次即可,性能好

劣势:当有多个需要指定this的方法时,需要在 constructor 中 bind 多个,略显繁琐

  1. 在绑定事件时使用 bind 方法

     render() {
         return (
             <button onClick={this.click.bind(this)}>ClickPaas</button>
         )
     }
    复制代码

原理:同第一种方式的原理一样

优势:可读性强?

劣势:每次 render 都会重新 bind 一次,性能差

  1. 在绑定事件时使用箭头函数

     render() {
         return (
             <button onClick={() => this.click()}>ClickPaas</button>
         )
     }
    复制代码

原理:ES6 新增的箭头函数没有自身的 this, 它继承上下文中的 this,指向当前组件

优势:不需要考虑this的指向

劣势:每次 render 都会产生一个新的回调函数,性能差

  1. 将定义在原型上面的方法改为实例方法

     export default class Header extends PureComponent {
         constructor() {
             super()
             this.state = {}
         }
         
         // 实例方法
         click = () => {
             console.log(this)
         }
         
         render() {
             return (
                 <button onClick={this.click}>ClickPaas</button>
             )
         }
     }
    复制代码

原理:同第三种方式的原理一样

优势:性能比第二种、第三种方式要好

劣势:将原型方法变成了实例方法,有一定的内存开销

最后

文中如有错误,欢迎在评论区指正,谢谢阅读

转载于:https://juejin.im/post/5c9c7b12f265da6102099e82

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值