react中的事件绑定

遇到的问题

最近想试一下React,之前一直用Vue在写东西。稍微看了几篇教程后,就开始写,能够基本运行起来,可能是因为项目比较简单吧。但是也遇到了几个问题,首先就是React的事件绑定问题

我第一次的写法是:

1
2
3
4
5
handleEvent(){
console.log("test")
}

<Button onClick="handleEvent"> </Button>

这样普通的点击事件是能够正常触发的。

this的指向问题

但是当我要使用this时,这种写法就出了问题。

1
2
3
4
5
6
7
handleEvent(){
this.setState({
state1 : 111
})
}

<Button onClick="handleEvent"> </Button>

这样就会报错this为undefined的。于是我就想起了之前看过的文章以及结合之前对JavaScript的函数的this分析。就明白此时函数在调用时不是被react对象直接调用的。所以该函数的this的指向为undefined。所以要想使用react对象的方法,只有将函数的this指向为react。根据之前文章对this的分析,要想绑定this,可以使用:

  1. call(一次绑定并调用)

  2. apply (一次绑定并调用)

  3. bind(永久绑定)

  4. 箭头函数 () => {}永久绑定

但是事件是要多次调用并且不是绑定时就调用,而是事件被触发时才调用,所以排除call与apply方法。所以选择bind与箭头函数为最佳(后来看官方文档时发现官方也是推荐了这两种方法来绑定this)。

所以有以下方法:

  1. 在构造函数中绑定函数的this指向

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    constructor(props){
    super(props)
    this.handleEvent = this.handleEvent.bind(this)
    }

    handleEvent(){
    console.log(this) //此时指向react对象
    }

    <Button onClick={handleEvent}></Button>
  2. 在事件绑定时绑定函数this

    1
    2
    3
    4
    5
    handleEvent(){
    console.log(this) //此时指向react对象
    }

    <Button onClick={this.handleEvent.bind(this)}></Button>

至此,this的指向问题基本解决。

函数传参的问题

接下来遇到需要传参的函数。我使用了与Vue与原始HTML同样的写法

1
2
3
4
5
handleEvent = (para) => {
console.log(para)
}

<Button onClick={this.handleEvent("123")}></Button>

当我尝试触发事件时,发现事件触发不成功,并且在打开控制面板时发现在页面初始化时,该事件被自动触发了3次,点击按钮无法触发。于是我不禁思考JSX的语法,让我想到了EL表达式EL表达式中的代码会被直接运行,该位置会被填充为运行后的结果。再来看这个问题就发现自己的问题了。

{}内的代码在JSX模板编译时被当成代码直接运行,而tihs.handleEvent("123")在JavaScript中不就是直接运行函数吗,所以函数在模板编译时直接被运行了,而onClick的事件则被绑定为函数的返回值,但是这个函数没有返回值,所以事件绑定失败。

所以如何解决这个问题就很简单了,只要在事件绑定的位置放置一个函数而不是函数的调用就行了,方法也有两个:

  1. bind方法传参

    1
    2
    3
    4
    5
    handleEvent = (para) => {
    console.log(para)
    }

    <Button onClick={this.handleEvent.bind(this,"123")}></Button>
  2. 箭头函数

    1
    2
    3
    4
    5
    handleEvent = (para) => {
    console.log(para)
    }

    <Button onClick={() => {this.handleEvent(123)}}></Button>

    折腾一下

    在看到箭头函数时我又思考能不能不用箭头函数,直接用匿名函数实现函数的调用。像这样:

    1
    2
    3
    4
    5
    handleEvent = (para) => {
    console.log(para)
    }

    <Button onClick={function(para){this.handleEvent(para)}}></Button>

    再一想发现好想更不行,匿名函数没有绑定this指向。所以也就拿不到this.handleEvent()函数了。那就试试绑定一下匿名函数的this指向,像这样:

    1
    2
    3
    4
    5
    handleEvent = (para) => {
    console.log(para)
    }

    <Button onClick={function(){this.handleEvent(123)}.bind(this)}></Button>

    OK,事件成功绑定,但是转念一想,这么搞还不如直接bind原函数,也避开了使用箭头函数。纯属折腾吧。

    获取事件对象event

    在Vue或者原生HTML中,event被存储在window下的event对象中,在绑定事件时将event对象传入即可获得点击事件对象。

    但在React中,我们可以这么做:

    1. 当我们不需要为这个函数传参时,event对象会自动传入该函数,我们通过第一个参数获取event对象

    2. 当我们需要传参时,我们需要手动传入event对象

      1
      2
      3
      4
      5
      6
      7
      8
      handleEvent = (para,e) => {
      console.log(para)
      console.log(e)
      }

      <Button onClick={(e) => {this.handleEvent(123,e)}}></Button>
      //或者这样
      <Button onClick={this.handleEvent(123,e)}></Button>

Last

至此,React中的函数事件绑定基本可以搞定。写了一段时间的React,感觉相较于Vue,更灵活。刚入手的话,习惯了Vue模板文件的 <template> <style> <script>这种分明的设计,React中的JSX写起来感觉有点复杂。在对比anted与elemenui,感觉elementui的api简直太简单了。后期在多体验看看吧!

Powered by Hexo and Hexo-theme-hiker

Copyright © 2019 - 2024 My Wonderland All Rights Reserved.

UV : | PV :