React事件处理函数this指向解析

我们知道,由于浏览器的工作原理,事件处理函数当中的this都是指向当前的绑定了事件处理函数的DOM节点对象。但是一般在开发过程中我们都需要其内部的this指向的应该是这个组件的实例本身。常用的有以下三种方法:

方法一

export default class Test extends React.Component {
  constructor () {
    super()
    this.value = 1
    this.handleClick = this.handleClick.bind(this)
  }

  handleClick () {
    console.log(this.value)
  }

  render () {
    return <div>
      <button onClick={this.handleClick}>点我</button>
    </div>
  }
}

这种方法是由我们在构造函数中手动为事件处理函数硬绑定this。

方法二

export default class Test extends React.Component {
  constructor () {
    super()
    this.value = 1
  }

  handleClick () {
    console.log(this.value)
  }

  render () {
    return <div>
      <button onClick={this.handleClick.bind(this)}>点我</button>
    </div>
  }
}

这种方法其实和第一种应该是一样的,只不过绑定的位置发生了变化而已。

方法三

export default class Test extends React.Component {
  constructor () {
    super()
    this.value = 1
  }

  handleClick (e) {
    console.log(e)
    console.log(this.value)
  }

  render () {
    return <div>
      <button onClick={(e) => {
        this.handleClick(e)
      }}>点我
      </button>
    </div>
  }
}

第三种方法运用的是箭头函数内部this不可变性 (不可变性不是指箭头函数内部的 this永远指向一致,而是指其内部的 this永远指向箭头函数被定义时外部最近的 this

在这种情况下,由于事件处理函数是一个箭头函数,那没箭头函数内部的this指向就不可以被改变了,this指向离箭头函数最近的外部this,而render()方法中的this由于react的自动绑定机制,this指向实例本身,所以箭头函数的this也指向实例本身。而this.handleClick()这种调用方式其实和handleClick.apply(this)是等效的,所以这种写法也可以。

ES7的写法

export default class Test extends React.Component {
  constructor () {
    super()
    this.value = 1
  }

  handleClick = (e) => {
    console.log(e)
    console.log(this.value)
  }

  render () {
    return <div>
      <button onClick={this.handleClick}>点我</button>
    </div>
  }
}

不过,在Class中直接赋值是ES7的写法(其实和下面的写法等价),ES6并不支持,只用ES6的话可以用下面写法

export default class Test extends React.Component {
  constructor () {
    super()
    this.value = 1
    this.handleClick = (e) => {
      console.log(e)
      console.log(this.value)
    }
  }

  render () {
    return <div>
      <button onClick={this.handleClick}>点我</button>
    </div>
  }
}

总结

介绍了五种写法,总的来说可以分为两类,前三种是一类,后两种算一类。这两类最大的区别就是前者的事件处理函数是定义在类的原型之上,实现了代码的复用。而后者的事件处理函数是作为实例属性,每个类的实例在实例化时都需要定义一遍事件处理函数。

参考链接

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 函数参数的默认值 基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。 上面代码检查函数l...
    呼呼哥阅读 3,523评论 0 1
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,168评论 19 139
  • 睡了很久很久 、梦中的自己没有勇气,好象一个阳光匮乏的冬日,一切都因冰冷而蜷缩,于是爱情也随之模糊,不在清晰。确...
    红得不像话阅读 295评论 0 4
  • 当我们想要变得更自由、更喜悦和富足的时候,我们其实是有两条路,路不在远方,而在脚下: 一条路是下旋的地狱之路,我们...
    齐文系统排列阅读 410评论 0 0
  • 今天在和小伙伴在看一功能时,发现某个效果图很类似 淘宝的一个滑动,于是好奇的看了下淘宝和天猫的,先上效果图: 之前...
    天空中的球阅读 2,040评论 3 16