博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
为什么在React Component需要bind绑定事件
阅读量:5876 次
发布时间:2019-06-19

本文共 3450 字,大约阅读时间需要 11 分钟。

我们在 React class Component 绑定事件时,经常会通过 bind(this) 来绑定事件,比如:

class Foo extends React.Component{  constructor( props ){    super( props );    this.handleClick = this.handleClick.bind(this);  }  handleClick(event){    // todo something  }  render(){    return (          );  }}复制代码

下面就要看为什么我们需要bind(this)在组件中。

JavaScript 中 this 绑定机制

默认绑定(Default Binding)

function display(){ console.log(this); // this 指向全局对象}display(); 复制代码

display( )在全局的 window 作用域调用,所以函数内的 this 默认指向全局的 window, 在 strict 模式 this 的值为undefined。

隐式绑定(Implicit binding)

var obj = { name: 'coco', display: function(){   console.log(this.name); // this 指向 obj  }};obj.display(); // coco复制代码

当我们通过obj调用 display( ) 时,this 上下文执行 obj, 但是当我们将 display( ) 赋给一个变量,比如:

var name = "oh! global";var outerDisplay = obj.display;outerDisplay(); // oh! global复制代码

display 被赋给 outerDisplay 这个变量,调用 outerDisplay( ) 时,相当于 Default Binding,this 上下文指向 global, 因此 this.name 找到的是全局的 name。
很多时候,我们需要将函数作为参数通过callback方式来调用,也会使这个函数失去它的 this 上下文,比如:

function handleClick(callback) {  callback()}var name = 'oh! global';handleClick(obj.display);// oh! global复制代码

当调用handleClick方法时,JavaScript重新将 obj.display 赋予 callback 这个参数,相当于 callback = obj.display ,display这个函数在handleClick作用域环境,就像Default Binding,里面的 this 执行全局对象。

显式绑定(Explicit binding)

为了避免上面问题,我们可以通过 bind( ) 来显式绑定 this 的值。

var name = "oh! global";obj.display = obj.display.bind(obj); var outerDisplay = obj.display;outerDisplay();// coco复制代码

真正的原因在 JavaScript 不在 React

回到开始我们的问题:为什么 React 组件事件绑定需要 bind 来绑定,如果我们不绑定,this 的值为 undefined。

class Foo {  constructor(name){    this.name = name  }  display(){    console.log(this.name);  }}var foo = new Foo('coco');foo.display(); // coco// 下面例子类似于在 React Component 中 handle 方法当作为回调函数传参var display = foo.display;display() // TypeError: this is undefined复制代码

我们在实际 React 组件例子中,假设 handleClick 方法没有通过 bind 绑定,this 的值为 undefined, 它和上面例子类似handleClick 也是作为回调函数传参形式。
但是我们代码不是在 strict 模式下, 为什么 this 的值不是全局对象,就像前面的 default binding,而是undefined?
因为 class 类不管是原型方法还是静态方法定义,“this”值在被调用的函数内部将为 undefined,具体原因见 。
同样,我们为了避免这个问题需要 bind 绑定:

class Foo {  constructor(name){    this.name = name    this.display = this.display.bind(this);  }  display(){    console.log(this.name);  }}var foo = new Foo('coco');foo.display(); // cocovar display = foo.display;display(); // coco复制代码

当然,我们可以不在 constructor 中绑定 this, 比如:

var foo = new Foo('coco');foo.display = foo.display.bind(foo);var display = foo.display;display(); // coco复制代码

但是,在 constructor 中绑定是最佳和最高效的地方,因为我们在初始化 class 时已经将函数绑定,让 this 指向正确的上下文。

不用bind 绑定方式

当然,实际写 React Component 还有其他的一些方式来使 this 指向这个 class :
最常用的
public class fields

class Foo extends React.Component{  handleClick = () => {    console.log(this);   }   render(){    return (          );  }}复制代码
这是因为我们使用 语法,handleClick 箭头函数会自动将 this 绑定在 Foo 这个class, 具体就不做探究。

箭头函数

class Foo extends React.Component{  handleClick(event) {    console.log(this);   }   render(){    return (          );  }}复制代码

这是因为在ES6中,箭头函数 this 默认指向函数的宿主对象(或者函数所绑定的对象)。

其他

其他还有一些方法来使 this 指向 Foo 上下文,比如通过 ::绑定等,具体就不展开。

总结

React class 组件中,事件的 handle 方法其实就相当于回调函数传参方式赋值给了 callback,在执行 click 事件时
类似 element.addEventListener('click', callback, false ), handle 失去了隐式绑定的上下文,this 的值为 undefined。(为什么是 undefined 而不是 global,上文有解释)。
所以我们需要在 初始化调用 constructor 就通过 bind() 绑定 this, 当然我们不用 bind( )方式来绑定也可以有其他一些方法来时 this 指向正确的上下文。

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

你可能感兴趣的文章
js提交图片转换为base64
查看>>
学习CodeIgniter框架之旅(二)继承自定义类
查看>>
Y2161 Hibernate第三次考试 2016年8月18日 试卷分析
查看>>
Angular CLI 使用教程指南参考
查看>>
PHP 程序员的技术成长规划
查看>>
用于守护进程的出错处理函数
查看>>
memcached 分布式聚类算法
查看>>
禁止body滚动允许div滚动防微信露底
查看>>
Xtreme8.0 - Kabloom dp
查看>>
jquery css3问卷答题卡翻页动画效果
查看>>
MDK5.00中*** error 65: access violation at 0xFFFFFFFC : no 'write' permission的一种解决方法
查看>>
Android 集成支付宝支付详解
查看>>
SQL分布式查询、跨数据库查询
查看>>
C#------连接SQLServer和MySQL字符串
查看>>
Arcgis Licensemanager 不能启动的原因之一(转载)
查看>>
(原)Android在子线程用handler发送的消息,主线程是怎么loop到的?
查看>>
$digest already in progress 解决办法——续
查看>>
虚拟机 centos设置代理上网
查看>>
Struts2中Date日期转换的问题
查看>>
mysql 数据类型
查看>>