2016-07-07 63 views
-1

我在我的顶级React组件中有很多方法,我想在其子组件中使用回调。我明白,在ES6中,我必须手动绑定每种方法的上下文。我目前的构造方法看起来像这样:在构造函数()中绑定许多React组件方法的上下文的正确约定是什么?

this.method1 = this.method1.bind(this); 
this.method2 = this.method2.bind(this); 
this.method3 = this.method3.bind(this); 
... 

This works;我所有的孩子都可以在他们调用回调的时候保留预期的上下文,但似乎有很多代码需要写出来,我甚至不需要在ES5中编写这些代码。有没有一种快速的方法将上下文绑定到我的所有组件方法而无需编写所有这些样板文件?

+0

我建议你看看我的答案,即使@naomik downvoted和标记为删除。这是直接来自Facebook的解决方案,并解释了原因。 – mtaube

回答

-1

如果您使用的是Babel,则可以启用阶段0并使用此绑定运算符::

您应该能够传递给孩子,当绑定到父上下文:

method1() { 
    ... 
} 

render() { 
    return <ChildComponent method1={::this.method1} />; 
} 

https://babeljs.io/docs/plugins/preset-stage-0/
http://babeljs.io/docs/plugins/transform-function-bind/

+1

我相信这意味着每次调用'render''时都要绑定这个方法,这是不好的做法。 – mtaube

+0

导致性能问题?我认为他的目标也可以通过箭头函数作为类属性来实现。 –

0

我明白,在ES6我必须手动绑定每个上下文方法。

是的,除非这不完全正确。 ES6允许你表达比ES5更好的东西。

在ES6中编写代码并不意味着您直接翻译了ES5中的代码。使用当前版本的React中的新功能以及ES6原生的功能,有更多的惯用方法可以实现它。

import {Component} from 'react' 

class Foo extends Component { 
    // this class doesn't even need constructor 

    createButton(text) { 
    // don't write 
    // return <button onclick={this.handleClick.bind(this)}>{text}</button> 
    // instead write 
    return <button onclick={e=> this.handleClick(e)}>{text}</button> 
    } 

    handleClick(event) { 
    console.log(event, 'button was clicked') 
    } 

    render() { 
    var {buttons} = this.props; 
    // don't write 
    // return <div>{buttons.map(this.createButton.bind(this)}</div> 
    // instead write 
    return <div>{buttons.map(this.createButton, this)}</div> 
    } 
} 

export default Foo; 

// <Foo buttons={["one", "two", "three"]} /> 

通知我用两种不同的方式背景下,并不需要有一个词汇this因此具有约束力并不在大多数情况下需要Function.prototype.bind

  1. 箭头功能。箭头功能是ES6的新功能。
  2. Array.prototype功能mapreduceforEach接受thisArgument,它允许您更改回调的背景下。这对于ES6来说并不陌生,所以今天在ES5代码中没有什么能阻止你使用它。

但是你也看到这是一个stateless functional component?无状态的功能组件可作为阵营0.14

在惯用的阵营代码,大多数你写会是无状态的,只是构成其他组件的组件。我们正在推出一个新的,更简单的语法为这些组件,您可以采取的道具作为参数,并返回要渲染的元素

来源:React Blog v0.14

这段代码功能相同以上,但该组件不需要class或上下文仪式

const createButton = (text) => { 
    return <button onClick={handleClick}>{text}</button> 
} 

const handleClick = (event) => { 
    console.log(event, 'button was clicked') 
} 

// stateless functional component 
const Foo = ({buttons}) => { 
    return <div>{buttons.map(createButton)}</div> 
} 

export default Foo; 

当然,这种方法不能用于组件的工作,我nvolve state(或生命周期方法),但它适用于任何仅使用props的组件 - 这是您的大部分组件。

这只是一个技巧,你必须以一种惯用的方式编写React应用程序,不涉及Function.prototype.bind

对于它的价值,我已经多年没有依赖Function.prototype.bind(有我写的代码)。

+0

您使用箭头函数和数组原型函数提出的解决方案涉及绑定多次。 React/Facebook不建议这样做。 [从那里获得文档](https://facebook.github.io/react/docs/reusable-components.html#es6-classes):“我们建议你在构造函数中绑定你的事件处理程序,以便它们只绑定一次每个实例,这对你的应用程序的性能更好,特别是如果你在子组件中使用浅比较来实现shouldComponentUpdate()。 – mtaube

-2

这里有各种有效的方法;所述一个我喜欢是使用@autobind装饰:

import autobind from 'autobind-decorator'; 

class MyComponent extends React.Component { 
    @autobind 
    method1() { 
     // "this" is bound correctly 
    } 
} 

这需要autobind-decorator模块(或core-decorators,它公开了一个类似的功能),加babel-preset-decorators-legacy

+1

你绝对应该提到装饰模块只存在于人们从babel 5到babel 6的简单转换中,而装饰者目前不是规范的一部分。 – naomik

+0

@naomik - 如果你使用'decorators-legacy'预设,那没什么用 - 它会在Babel和ES7发展的时候继续工作。当规范被解决时,大概装饰器软件包会更新以支持新的API。 – nrabinowitz

相关问题