转载

使用ES6编写React应用(3):React类中方法的绑定

本文是使用ES6来编写React应用系列的第三篇,本文主要将讨论的是React类中方法的绑定问题。 本篇博文的主要目的是解决前一篇文章中的遗留问题。

Statement

  • 作者: 景庄 ,Web开发者,主要关注JavaScript、Node.js、React、Docker等。
  • 源码: 本文的源代码地址:https://github.com/wwsun/react-es6-tutorial

介绍

如果你阅读并尝试过前一篇文章中的 CartItem 组件的render方法 , 你可能会对其中使用 {this.increaseQty.bind(this)} 这样的语句感到困惑。 我们的直觉是直接使用 <button onClick={this.increaseQty} className="button success">+</button> 这样的代码。 如果你真的尝试这么做了,我们将会在浏览器的控制台中看到这样的一条错误:

Uncaught TypeError: Cannot read property 'setState' of undefined 

如下图所示:

使用ES6编写React应用(3):React类中方法的绑定

这是因为如果我们使用这种方式调用函数的话,此时的 this 并没有绑定到类本身,而是 undefined 。 这是JavaScript的默认行为。相反,如果你使用 React.createClass() 来创建组件的话, 所有的方法都会被自动绑定到对象的实例上。对一些开发者而言,这可能有点反直觉。

之所以没有使用自动绑定,是因为React开发组在决定实现组件对ES6类的支持时决定的。 如果你想了解更详细的原因,你可以通过这篇博文了解更多。

下面我们来进一步的讨论,如果你使用的是ES6类的话,如何在JSX中使用不同的方式调用类方法。

方法1:使用 Function.prototype.bind()

这也就是我们已经在前一篇博文中使用过的方法:

class CartItem extends React.Component {   render() {     <button onClick={this.increaseQty.bind(this)} className="button success">+</button>   } } 

由于ES6类中的任何一个方法都是普通的JavaScript函数,它从Function原型中继承了 bind() 方法。 因此如果我们需要在JSX中调用 increaseQty()this 将会指向我们的类实例。 你可以从 MDN文章 中获取更多的有关 Function.prototype.bind() 方法的内容。

方法2:在构造器中使用被定义的函数

我们还可以通过在类的构造器中解决函数绑定的问题,代码如下:

class CartItem extends React.Component {          constructor(props) {         super(props);         this.increaseQty = this.increaseQty.bind(this);     }      render() {         <button onClick={this.increaseQty} className="button success">+</button>     } }  

这样,你就无需在JSX中再使用 bind() 方法了,但这种方法的缺点是增加了构造器的代码,并且让构造器不再优美。

方法3:使用胖箭头函数 => 和构造器

ES6胖箭头函数会在它们被调用的时候自动保存 this 上下文。我们可以通过这个特性来重新咋构造器中定义 increaseQty()

class CartItem extends React.Component {          constructor(props) {         super(props);         this._increaseQty = () => this.increaseQty();     }      render() {         <button onClick={this._increaseQty} className="button success">+</button>     } } 

小结

在本文中,我们主要讨论几种使用ES6代码来解决绑定到React组件方法的可行方案。 总体而言,由于JavaScript语言的自身特性,我们很难有一个统一的优雅的解决方案, 因此,我更偏向于使用第一种方法,在JSX中进行手动绑定。当然,在未来,ECMAScript标准将有更加优雅的解决方案。 如果你感兴趣的话,可以阅读 这篇文章 。

References

  1. About autobinding in official React blog
  2. Auto binding, React and ES6 Classes
  3. Function Bind Syntax in Official Babel Blog
  4. Function.prototype.bind()
原文  http://wwsun.github.io/posts/react-with-es6-part-3.html
正文到此结束
Loading...