为什么React事件处理函数必须使用Function.bind()绑定this?

最近在React官网学习Handling Events这一章时,有一处不是很明白。代码如下:

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? ‘ON‘ : ‘OFF‘}
      </button>
    );
  }
}

ReactDOM.render(
  <Toggle />,
  document.getElementById(‘root‘)
);

注意到在Toggle类的构造函数constructor类中,有一句注释:“This binding is necessary to make `this` work in the callback”,即在构造函数中,利用Function.bind()函数将类中已有的handleClick函数再次绑定了一下this。对于这个做法,官网给出的注释是:

这段话说了看似说了很多,其实就两点:

1.如果你不绑定this.handleClick方法,那么在事件发生并且精确调用这个方法时,方法内部的this会丢失指向。2.这不是React的原因,这是JavaScript中本来就有的。如果你传递一个函数名给一个变量,然后通过在变量后加括号()来调用这个方法, 此时方法内部的this的指向就会丢失

这一段点明了为什么要在构造函数中绑定this,因为JavaScript中确实有这么一个陷阱。具体是怎么样的呢?我进行了一下测试:

let obj = {
    tmp:‘Yes!‘,
    testLog:function(){
        console.log(this.tmp);
    }
};
obj.testLog();

为了便于为学习ES6的童鞋理解以及说明这是JavaScript中的陷阱而非React所特有,这里使用字面量表达式声明对象。

经过测试,这样使用obj中的testLog方法时,this指向obj,能够正常输出tmp属性:

现在修改一下代码:

let obj = {
    tmp:‘Yes!‘,
    testLog:function(){
        console.log(this.tmp);
    }
};
let tmpLog = obj.testLog;
tmpLog();

注意到现在没有直接调用obj对象中的testLog方法,而是使用了一个中间变量tmpLog过渡,当使用括号()调用该方法时,方法中的this丢失了指向,会指向window,进而window.tmp未定义就是undefined:

说了这么多,跟React事件处理函数的绑定有什么关系呢?

前面讲过,React跟原生JavaScript的事件绑定区别有两点,其中第二点就是:

即在React(或者说JSX)中,传递的事件参数不是一个字符串,而是一个实实在在的函数:

这样说,React中的事件名(上图中的onClick)就是我所举例子中的中间变量,React在事件发生时调用onClick,由于onClick只是中间变量,所以处理函数中的this指向会丢失,为了解决这个问题,我们需要在实例化对象的时候,需要在构造函数中绑定this,使得无论事件处理函数如何传递,它的this的指向都是固定的,固定指向我们所实例化的对象。

这个JavaScript陷阱是对我之前文章关于JavaScript中的this的一个很好的补充。

时间: 2024-10-12 20:11:53

为什么React事件处理函数必须使用Function.bind()绑定this?的相关文章

(转)React事件处理函数必须使用bind(this)的原因

1.JavaScript自身特性说明如果传递一个函数名给一个变量,之后通过函数名()的方式进行调用,在方法内部如果使用this则this的指向会丢失.示例代码:首先我们创建test对象并直接调用方法 : const test = { name:'jack', getName:function(){ console.log(this.name) }}test.getName()1234567使用node test.js执行上述代码可以正常输出jack. 之后,我们对代码进行调整: const te

React 事件处理函数

触摸事件:onTouchCancel\onTouchEnd\onTouchMove\onTouchStart (只会在移动设备上接受) 键盘事件:onKeyDown\onKeyPress\onKeyUp 剪切事件:onCopy\onCut\onPaste 表单事件:onChange\onInput\onSubmit 焦点事件:onFocus\onBlur UI元素:onScroll(移动设备是手指滚动和PC的鼠标滑动) 滚动事件:onWheel(鼠标滚轮) 鼠标类型:onClick\onCont

Jquery动态绑定事件处理函数 bind / on / delegate

1.bind方法绑定的事件处理函数不会应用到后来添加到DOM中的新元素.比如你在用bind给页面元素绑定事件之后,又新添加了一些与之前绑定过事件的元素一样的DOM元素,但是这些事件并不能在新的DOM元素上有体现. 如: $(document).ready(function(){ $("img").bind({ mouseenter:function(){ $(this).css("border","thick solid red"); }, mo

函数指针,function,bind, lambda

函数指针,sd::function<type1, type2...> functionObject, std::bind() 1. 函数指针是类型不安全的,为什么? #include<stdio.h> int max(int x,int y){return (x>y? x:y);} int main() { int (*ptr)(int, int); int a, b, c; ptr = max; scanf("%d%d", &a, &b)

function/bind 函数适配器

1.function/bind简介 function是一种类模板,重载了operator()函数调用操作符,所以每一个function类的对象都是一个函数对象. bind是一种函数适配器,可以改变参数的个数.顺序. 2.相关代码 1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <functional> 5 using namespace std; 6 7 voi

jquery事件之事件处理函数

一.事件处理 方法名 说明 语法 (events 事件类型,data数据,handler 事件处理函数,selector 选择器) Bind( 为每一个匹配元素的特定事件(像click)绑定一个事件处理器函数.没用on关键字 jQueryObject.bind( events [, data ], handler ) One 为每一个匹配元素的特定事件(像click)绑定一个一次性的事件处理函数.只绑定一次 jQueryObject.one( events [, data ], handler 

JQuery事件绑定函数:on()与bind()的差别

JQuery从1.7+版本开始,提供了on()和off(),进行事件处理函数的绑定和取消.这2个API与JQuery最初提供的bind()和unbind()有很多相似的地方,也有一些不同之处.bind和unbind的详细介绍,可以参考这篇文章. on()和bind()的函数签名如下: bind(type, [data], fn) on(type,[selector],[data],fn) 可以看到2个函数的区别在于:是否支持selector这个参数值.由于javascript的事件冒泡特性,如果

JQuery事件绑定函数one:绑定的事件处理函数只会被执行一次

JQuery绑定事件处理函数,有两种方式(方式1和方式2)是最常用的,方式3使用的较少. 方式1: $("#button").click(function(){ }); 这种方式很简单,也是平时编码最常用的做法.HTML中原始的事件,如onclick.onmouseover.onkeypress等,JQuery对名称进行了简单的封装,如onclick与JQuery的click对应,onmouseover与JQuery的mouseover对应.查看JQuery的API可以发现:JQuer

给wxPython事件处理函数传递参数

给wxPython事件处理函数传递参数 2014-04-30 07:47:08segmentfault-博客--点击数:39 最近捣鼓Python,也就自然捣鼓上了wxPython.我曾经用过Qt和Gtk+写GUI,但几乎所有的Python书都告诉我说最好用的是wxPython,我没有尝试PyQt和PyGtk就开始研究wxPython了.在Qt和Gtk+之间我更喜欢Qt,因为它跨平台做得很好,而且商业化也不错.但wxWidget给人的感觉就完全不同了. 如果说wxWidgets相对于Qt有什么优