如何使用箭头函数(公共类字段)作为类方法?

我是用React使用ES6类的新手,以前我一直在绑定我的方法到当前对象(在第一个例子中显示),但ES6允许我永久绑定一个类函数到一个类实例与箭头?(在作为回调函数传递时有用。)我得到错误时,我试图使用他们,因为你可以与CoffeeScript:

class SomeClass extends React.Component {


// Instead of this
constructor(){
this.handleInputChange = this.handleInputChange.bind(this)
}


// Can I somehow do this? Am i just getting the syntax wrong?
handleInputChange (val) => {
console.log('selectionMade: ', val);
}

因此,如果我将SomeClass.handleInputChange传递给,例如setTimeout,它的作用域将是类实例,而不是window对象。

132962 次浏览

你的语法有点错误,只是在属性名后面少了一个等号。

class SomeClass extends React.Component {
handleInputChange = (val) => {
console.log('selectionMade: ', val);
}
}

这是一个实验特性。你需要在Babel中启用实验特性来编译。在这里是一个实验性启用的演示。

要在babel中使用实验特性,可以从在这里安装相关插件。对于这个特定的特性,你需要transform-class-properties插件:

{
"plugins": [
"transform-class-properties"
]
}

你可以阅读更多关于类字段和静态属性在这里的建议


不,如果你想创建绑定的,特定于实例的方法,你必须在构造函数中这样做。但是,你可以使用箭头函数,而不是在原型方法上使用.bind:

class SomeClass extends React.Component {
constructor() {
super();
this.handleInputChange = (val) => {
console.log('selectionMade: ', val, this);
};
…
}
}

有一个建议,它可能允许你省略constructor(),并直接将赋值放在类作用域中,具有相同的功能,但我不建议使用它,因为它是高度实验性的。

或者,您总是可以使用.bind,它允许您在原型上声明方法,然后将其绑定到构造函数中的实例。这种方法具有更大的灵活性,因为它允许从类外部修改方法。

class SomeClass extends React.Component {
constructor() {
super();
this.handleInputChange = this.handleInputChange.bind(this);
…
}
handleInputChange(val) {
console.log('selectionMade: ', val, this);
}
}

我知道这个问题已经得到了充分的回答,但我还有一个小小的贡献要做(对于那些不想使用实验功能的人)。由于必须在构造函数中绑定多个函数绑定的问题,使它看起来很混乱,我提出了一个实用方法,一旦在构造函数中绑定和调用,就会自动为您执行所有必要的方法绑定。

假设我有一个带有构造函数的类:

//src/components/PetEditor.jsx
import React from 'react';
class PetEditor extends React.Component {
  

constructor(props){
super(props);
this.state = props.currentPet || {tags:[], photoUrls: []};
     

this.tagInput = null;
this.htmlNode = null;


this.removeTag = this.removeTag.bind(this);
this.handleChange = this.handleChange.bind(this);
this.modifyState = this.modifyState.bind(this);
this.handleKeyUp = this.handleKeyUp.bind(this);
this.addTag = this.addTag.bind(this);
this.removeTag = this.removeTag.bind(this);
this.savePet = this.savePet.bind(this);
this.addPhotoInput = this.addPhotoInput.bind(this);
this.handleSelect = this.handleSelect.bind(this);
        

}
// ... actual method declarations omitted
}

它看起来很乱,不是吗? 现在我创建了这个工具方法

//src/utils/index.js
/**
*  NB: to use this method, you need to bind it to the object instance calling it
*/
export function bindMethodsToSelf(objClass, otherMethodsToIgnore=[]){
const self = this;
Object.getOwnPropertyNames(objClass.prototype)
.forEach(method => {
//skip constructor, render and any overrides of lifecycle methods
if(method.startsWith('component')
|| method==='constructor'
|| method==='render') return;
//any other methods you don't want bound to self
if(otherMethodsToIgnore.indexOf(method)>-1) return;
//bind all other methods to class instance
self[method] = self[method].bind(self);
});
}

现在我所需要做的就是导入该实用程序,并向构造函数添加一个调用,我不再需要在构造函数中绑定每个新方法。 新的构造函数现在看起来很干净,就像这样:

//src/components/PetEditor.jsx
import React from 'react';
import { bindMethodsToSelf } from '../utils';
class PetEditor extends React.Component {
constructor(props){
super(props);
this.state = props.currentPet || {tags:[], photoUrls: []};
this.tagInput = null;
this.htmlNode = null;
bindMethodsToSelf.bind(this)(PetEditor);
}
// ...
}

你正在使用箭头函数,并在构造函数中绑定它。所以当你使用箭头函数时,你不需要做绑定

class SomeClass extends React.Component {
handleInputChange = (val) => {
console.log('selectionMade: ', val);
}
}

或者,当你使用下面这样的普通函数时,你只需要在构造函数中绑定一个函数

class SomeClass extends React.Component {
constructor(props){
super(props);
this.handleInputChange = this.handleInputChange.bind(this);
}


handleInputChange(val){
console.log('selectionMade: ', val);
}
}

另外,不建议直接在渲染中绑定函数。它应该总是在构造函数中