理解:为什么React事件处理中要绑定this

题外话


笔者刚换了家公司,公司用React框架,所以需要学习。目前大部分普通程序员身上所反映出来的通病就是,公司需要什么,就很快的去学习什么,对于知识的把握与理解程度,仅限于囫囵吞枣,当然更多的是项目紧赶时间,碰到问题,能百度就绝不去想(PS:哪有时间去想那么多为什么,赶快搞完下班)。所以虽然市面上很多程序员,但能力参差不齐,普遍质量不高。有能力的自然是大厂、高薪资、好待遇,那能力是怎样提升的,自然是累积的。笔者希望自己能在麻木的工作中保留那么一丝思考问题的能力。

说明


笔者写的东西都很基础,希望见微知著。写博客更多的是给自己看的,巩固加深自己对问题的理解。当然初期能力不足,对于问题的理解片面或有错误,大家发现望及时提醒指出,感激不尽。

言归正传


问题见于此(官网事件处理):

思考:为什么要改变this指向?
答:zz啊,人家不是都说了,为了在回调中使用this。

个人理解


上图定义了一个Toggle组件类,在使用 ReactDom.render() 方法将其渲染到界面上时,会生成组件实例,好比操作 new Toggle() 生成实例,那么显而易见,this最终指向新生成的实例。生成实例的过程中,构造器函数 constructor() 必执行。当执行到下面语句时,分析代码: this.handleClick = this.handleClick.bind(this);赋值语句右侧,this.handleClick 执行,首先在当前实例上查找 handleClick 方法,当前实例没有,然后沿原型链向上查找到原型方法 handleClick ,再执行 bind(this) ,将原型方法中的 this 指向新生成的实例

这也就理解了上面答案,为了在回调中使用 this 。如果不绑定 this ,此处的 this 是 undefined 。 这就完事了?并没有。
注意此时的 handleClick 方法已经由原型方法变为了实例方法,仔细体味赋值语句。
引申思考: 为什么要将原型方法转变为实例方法?
个人见解: ES6的继承,本质就是ES5的组合式继承,构造函数+原型链技术,也称伪经典继承。原型方法即在原型上定义的方法,目的是实现方法的复用。我现在变为实例方法,岂不是每个实例都有这个方法,失去了复用性?无可厚非,必须这么做,每个实例都有自己的 state 状态,我需要修改每个实例当前的 state 状态,每个实例的状态(/数据)具有密封性,通过自身的实例方法去修改,这也体现了面向对象思想的封装性。

对于事件处理另外两种方式的理解

其实理解了上述所说,这两种方式就很好理解。
第一种方式:

class LoggingButton extends React.Component {
  // 此语法确保 `handleClick` 内的 `this` 已被绑定。
  // 注意: 这是 *实验性* 语法。
  handleClick = () => {
    console.log('this is:', this);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}

理解:这是实例属性的新写法,相当于在构造函数内部声明了一个 handleClick 属性,采用箭头函数的目的是,让 this 指向当前实例。与绑定this的思想是一样的,每个实例上都会有此方法。
第二种方式:

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // 此语法确保 `handleClick` 内的 `this` 已被绑定。
    return (
      <button onClick={() => this.handleClick()}>
        Click me
      </button>
    );
  }
}

理解: 在 render() 函数中 this 即为组件实例,利用箭头函数自身没有 this 的特性, this 指向组件实例,再去调用 handleClick() 方法,根据谁调用 this , this 指向谁的原则,可知 handleClick() 函数内部的 this 是指向当前组件实例的。

结语


以上探讨的,说白了,就是 this 指向的问题,并不能算React的问题,当然 this 这也是一个老生常谈的话题。个人对此理解也不是很透彻,希望在看了《你不知道的Javascript》上卷第二部分后有一个深层次的理解,个人也推荐大家看这本书。





原文链接:juejin.im

上一篇:浅谈 this、call、apply 、 bind
下一篇:Serverless 时代前端避坑指南

相关推荐

  • 高频数据交换下Flutter与ReactNative的对比

    (标题图片来自网络,侵删) 后端使用go写的socketio服务模拟期货行情数据,每10ms推送10条行情数据 ReactNative已经尽力优化了。 Flutter由于没fluttersock...

    2 年前
  • 高性能迷你React框架 anu1.3.0 发布

    anujs1.3.0是一款高性能Reactlike框架,是目前世界上对React16兼容最好的迷你库。 自React16起,相继推出createContext,createPortal, creat...

    2 年前
  • 高德地图 react-amap 实战

    clipboard.png(https://img.javascriptcn.com/5a33946ad8c0ea8ee7870f74f331d0c0 "clipboard.png") reacta...

    9 个月前
  • 高品质 React UI 组件

    (https://img.javascriptcn.com/cca319311c2ea59a2b5cdaa63b997828)(https://link.funteas.com?target=http...

    2 年前
  • 骚操作!在react中使用vuex

    原文地址(https://github.com/zyl1314/blog/issues/12) 前言 笔者最近在学习使用,提到react就绕不过去。redux是一个状态管理架构,被广泛用于rea...

    2 年前
  • 项目文档说明:react + Ant Design 的 blog-react-admin

    效果图(https://img.javascriptcn.com/734ce56fe3a37ab11e9744473f56bae1 "效果图") 前言 此 blogreactadmin 项目是基...

    2 年前
  • 面试题:Hooks 与 React 生命周期的关系

    React 生命周期很多人都了解,但通常我们所了解的都是 单个组件 的生命周期,但针对 Hooks 组件、多个关联组件(父子组件和兄弟组件) 的生命周期又是怎么样的喃?你有思考和了解过吗,接下来我们将...

    10 个月前
  • 面试官:请你在React中引入Vue3的@vue/reactivity,实现响应式。

    前言 React的状态管理是一个缤纷繁杂的大世界,光我知道的就不下数十种,其中有最出名immutable阵营的redux,有mutable阵营的mobx,reacteasystate,在hooks诞生...

    4 个月前
  • 面试官我想做个Reacter(React路由)

    路由的基础用法回顾,源码study,文章首发于docs,求个star 依赖 路由依赖于 reactrouter ,但是一般 pc 路由使用 reactrouterdom ,它依赖于 reactrout...

    3 个月前
  • 面试中React与Vue的比对

    1.virtual dom 用JS模拟DOM结构,DOM变化的对比,放在JS层做,以提高重绘性能 DOM操作昂贵,JS运行效率高,要减少DOM操作 使用:snabbdom的使用 ...

    2 年前

官方社区

扫码加入 JavaScript 社区