简体   繁体   English

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

[英]How to use arrow functions (public class fields) as class methods?

I'm new to using ES6 classes with React, previously I've been binding my methods to the current object (show in first example), but does ES6 allow me to permanently bind a class function to a class instance with arrows?我是在 React 中使用 ES6 类的新手,之前我一直将我的方法绑定到当前对象(在第一个示例中显示),但是 ES6 是否允许我使用箭头将类函数永久绑定到类实例? (Useful when passing as a callback function.) I get errors when I try to use them as you can with CoffeeScript: (在作为回调函数传递时很有用。)当我尝试像 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);
  }

So that if I were to pass SomeClass.handleInputChange to, for instance setTimeout , it would be scoped to the class instance, and not the window object.因此,如果我将SomeClass.handleInputChange传递给例如setTimeout ,它将被限定为类实例,而不是window对象。

Your syntax is slightly off, just missing an equals sign after the property name.您的语法略有偏差,只是在属性名称后缺少等号。

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

This is an experimental feature.这是一个实验性功能。 You will need to enable experimental features in Babel to get this to compile.你需要在 Babel 中启用实验性功能才能编译它。 Here is a demo with experimental enabled. 是一个启用了实验性的演示。

To use experimental features in babel you can install the relevant plugin from here .要在 babel 中使用实验性功能,您可以从这里安装相关插件。 For this specific feature, you need the transform-class-properties plugin :对于此特定功能,您需要transform-class-properties插件

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

You can read more about the proposal for Class Fields and Static Properties here您可以在此处阅读有关类字段和静态属性提案的更多信息


No, if you want to create bound, instance-specific methods you will have to do that in the constructor.不,如果要创建绑定的、特定于实例的方法,则必须在构造函数中执行此操作。 However, you can use arrow functions for that, instead of using .bind on a prototype method:但是,您可以为此使用箭头函数,而不是在原型方法上使用.bind

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

There is an proposal which might allow you to omit the constructor() and directly put the assignment in the class scope with the same functionality, but I wouldn't recommend to use that as it's highly experimental.有一个建议可能允许您省略constructor()并直接将赋值放在具有相同功能的类范围中,但我不建议使用它,因为它是高度实验性的。

Alternatively, you can always use .bind , which allows you to declare the method on the prototype and then bind it to the instance in the constructor.或者,您始终可以使用.bind ,它允许您在原型上声明方法,然后将其绑定到构造函数中的实例。 This approach has greater flexibility as it allows modifying the method from the outside of your class.这种方法具有更大的灵活性,因为它允许从类的外部修改方法。

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

I know this question has been sufficiently answered, but I just have a small contribution to make (for those who don't want to use the experimental feature).我知道这个问题已经得到了充分的回答,但我只是想做出一点贡献(对于那些不想使用实验性功能的人)。 Because of the problem of having to bind multiple function binds in the constructor and making it look messy, I came up with a utility method that once bound and called in the constructor, does all the necessary method bindings for you automatically.由于必须在构造函数中绑定多个函数绑定并使其看起来很乱的问题,我想出了一个实用方法,一旦在构造函数中绑定和调用,就会自动为您完成所有必要的方法绑定。

Assume I have this class with the constructor:假设我有这个带有构造函数的类:

 //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 }

It looks messy, doesn't it?看起来很乱是不是? Now I created this utility method现在我创建了这个实用方法

 //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); }); }

All I now need to do is import that utility, and add a call to my constructor, and I don't need to bind each new method in the constructor anymore.我现在需要做的就是导入该实用程序,并添加对构造函数的调用,并且我不再需要在构造函数中绑定每个新方法。 New constructor now looks clean, like this:新的构造函数现在看起来很干净,像这样:

 //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); } // ... }

You are using arrow function and also binding it in constructor.您正在使用箭头函数并将其绑定在构造函数中。 So you no need to do binding when you use arrow functions所以当你使用箭头函数时你不需要做绑定

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

OR you need to bind a function only in constructor when you use normal function like below或者,当您使用像下面这样的普通函数时,您只需要在构造函数中绑定一个函数

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

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

Also binding a function directly in render is not recommended.也不推荐直接在渲染中绑定函数。 It should always be in constructor它应该总是在构造函数中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何为使用箭头函数的 class 方法的参数生成 jsdoc? - How to get jsdoc generation for parms of class methods that use arrow functions? 使用ECMAScript 6箭头函数作为类方法 - Use ECMAScript 6 arrow functions as class methods 在 TypeScript 中使用箭头函数:如何使它们成为类方法? - Using arrow functions in TypeScript: how to make them class methods? 反应-箭头函数错误(建议类字段) - React - Arrow functions error (proposal class fields) 如何在jQuery函数中使用类方法? - How use class methods in jQuery functions? 使用私有/受保护/公共字段和方法扩展类 - Extend a class with private/protected/public fields and methods 不能在 JSX 中在 class 的箭头函数处使用 `this` - Can not use `this` in JSX at arrow functions of class 如何在React组件上测试定义为箭头函数(类属性)的组件方法? - How do I test component methods on a React component that are defined as arrow functions (class properties)? 如何在包含函数的方法中使用类变量? - How to use class variables inside methods that contain functions? 在 JavaScript class 方法中,即使使用箭头函数也无法在 addEventListener() 中使用“this”。 如何解决这个问题 - In JavaScript class method, Unable to use 'this' inside addEventListener() even using arrow functions. how to solve this issue
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM