React.js ES6避免将“this”绑定到每个方法

最近,我开始修补React.js,我喜欢它。 我开始在常规的ES5中,以便弄清事情,这些文档都是用ES5编写的。

但是现在我想尝试ES6,因为它有光泽,新颖,而且似乎简化了一些东西。 我感到困扰的是,对于我添加到组件类中的每种方法,我现在都必须绑定“this”,否则它不起作用。 所以我的构造函数最终看起来像这样:

constructor(props) { super(props); this.state = { ...some initial state... } this.someHandler = this.someHandler.bind(this); this.someHandler = this.someHandler.bind(this); this.someHandler = this.someHandler.bind(this); this.someHandler = this.someHandler.bind(this); this.someHandler = this.someHandler.bind(this); this.someHandler = this.someHandler.bind(this); this.someHandler = this.someHandler.bind(this); } 

如果我要给class上添加更多的方法,这将会变得更大,更丑陋。

我的问题是,有没有办法解决这个问题,或者至less让它更容易,更短,更难看? 我想尝试使用ES6的一个主要原因是为了使我的代码更加简洁,但是正好相反。 任何build议或意见,将不胜感激。

对于类属性初始值设定项 ,有一个ES7build议,通过将箭头函数绑定到实例来避免需要在构造函数中进行绑定。 他们看起来像下面这样:

 class Foo extends React.Component { handleBar = () => { console.log('neat'); }; handleFoo = () => { console.log('cool'); }; render() { return ( <div onClick={this.handleBar} onMouseOver={this.handleFoo} /> ); } } 

Class属性初始值设定项由Babel通过其类属性转换实验性地支持,但由于它们是阶段2的提议(尚未在Babel预设中),所以它们仍然是“实验性的”。

但是,您需要手动执行绑定,直到ES7或在Babel中启用该function。 Babel在React on ES6 +上的博客文章简要介绍了这个话题。

另一种select是使用装饰器。 您在原型上声明了一个getter,并且在第一次访问实例时,它定义了一个具有该函数的绑定版本的属性。

但有一个问题! 在开发过程中,它不会取代这个属性,它会在每个访问上绑定。 这意味着你不要打破反应热装载机 。 至less对我来说,这非常重要。

我创build了一个库, class-bind ,提供了这个。

 import {bound} from 'class-bind'; class App { constructor(){ this.foo = 'bar'; } @bound returnsFoo(){ return this.foo; } render(){ var returnsFoo = this.returnsFoo; return ( <div> {returnsFoo()} === 'bar' </div> ); } } 

装饰者对你来说太不稳定了? 你可以绑定一切或一些东西具有相同的好处。

 import {bind, bindAll} from 'class-bind'; bind(App.prototype, 'returnsFoo'); // or bindAll(App.prototype); 

如果使用stage-0 ,则有一个函数绑定语法。

 class MyComp extends Component { handleClick() { console.log('doing things') } render() { return <button onClick={::this.handleClick}>Do Things</button> } } 

这破坏了this.handleClick.call(this) ,我认为这通常足够高性能。

Ssorallen的build议是伟大的,但如果你想另一种方式有:

  class AppCtrlRender extends Component { binder(...methods) { methods.forEach( (method) => this[method] = this[method].bind(this) ); } render() { var isMobile = this.state.appData.isMobile; var messages = this.state.appData.messages; return ( <div id='AppCtrlSty' style={AppCtrlSty}> React 1.3 Slider <br/><br/> <div className='FlexBoxWrap'> <Slider isMobile={isMobile}/> <JList data={messages}/> </div> </div> ); } } var getAppState = function() { return { appData: AppStore.getAppData() }; }; export default class AppCtrl extends AppCtrlRender { constructor() { super(); this.state = getAppState(); this.binder('appStoreDidChange'); } componentDidMount() { var navPlatform = window.navigator.platform; Actions.setWindowDefaults(navPlatform); } componentWillMount() { AppStore.onAny(this.appStoreDidChange); } componentWillUnmount() { AppStore.offAny(this.appStoreDidChange); } appStoreDidChange() { this.setState(getAppState()); } } 

您可以添加任何数量的方法this.binder('method1','method2',…)

一个想法,以避免绑定

 class MyComp extends Component { render() { return <button onClick={e => this.handleClick(e)}>Do Things</button> } } 

免责声明:未经testing,也不能轻易处理多于一个论点(在这种情况下,有一个事件(e)。

另外,这个答案可能是一个不能做的例子,根据这篇文章可能是值得一读的:

https://daveceddia.com/avoid-bind-when-passing-props/

我实际上更喜欢通过传递孩子的父上下文来模仿OOPinheritance。

 class Parent extends Component { state = {happy: false} changeState(happy) { this.setState({happy}) } render() { return ( <Child parent={this} > ) } } class Child extends Component { //... this.props.parent.changeState(true) } 

$ 0.02,Jon

我创build了一个方法来组织所有的“绑定”。

 class MyClass { constructor() { this.bindMethods([ 'updateLocationFields', 'render', 'loadCities', ]); } bindMethods(methods) { methods.map(item => this[item] = this[item].bind(this)); } ... }