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

Ben*_*Ben 168 javascript ecmascript-6 reactjs babeljs ecmascript-next

我刚接触使用带有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);
  }
Run Code Online (Sandbox Code Playgroud)

因此,如果我要传递SomeClass.handleInputChangesetTimeout它,那么它将被限定为类实例,而不是window对象.

Guy*_*Guy 195

您的语法略有偏差,只是在属性名称后面缺少等号.

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

这是一个实验性功能.您需要在Babel中启用实验性功能才能进行编译.是一个启用实验的演示.

要在babel中使用实验性功能,您可以从此处安装相关插件.对于此特定功能,您需要transform-class-properties插件:

{
  "plugins": [
    "transform-class-properties"
  ]
}
Run Code Online (Sandbox Code Playgroud)

您可以在此处详细了解类字段和静态属性的提议


  • 您应该提供一些解释,例如,这是ES7提案的实验性功能. (40认同)
  • 它可以工作,但是该方法被添加到构造函数中的实例中,而不是添加到原型中,并且它有很大的不同. (11认同)
  • (虽然我知道在ES6课程之外工作)对我来说似乎不起作用,但是babel会在第一个`=`处于`handleInputChange =`时抛出一个意外的标记箭头 (4认同)

Ber*_*rgi 60

不,如果要创建绑定的,特定于实例的方法,则必须在构造函数中执行此操作.但是,您可以使用箭头函数,而不是使用.bind原型方法:

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

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

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

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


ken*_*oft 6

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

假设我有这个类和构造函数:

//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
}
Run Code Online (Sandbox Code Playgroud)

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

//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);
         });
}
Run Code Online (Sandbox Code Playgroud)

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

//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);
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)


Hem*_*ari 5

您正在使用箭头函数并将其绑定在构造函数中。所以使用箭头函数时不需要进行绑定

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

或者,当您使用如下所示的普通函数时,您只需要在构造函数中绑定函数

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

  handleInputChange(val){
    console.log('selectionMade: ', val);
  }
}
Run Code Online (Sandbox Code Playgroud)

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