是否可以为React'打开React.js自动绑定;s类模型

Is it possible to turn on React.js autobinding for React's class model

本文关键字:React 绑定 模型 js 打开 是否      更新时间:2023-09-26

根据这篇博客文章,将React.createClassthis中的所有方法绑定在一起的特性是在React的类模型中没有内置

是否可以在默认情况下打开

我知道可以使用this.someMethod = this.ticksomeMethod.bind(this);技巧手动执行此操作,但是否可以为所有方法执行此操作?还是我被迫为所有方法编写bind

我现在拥有的代码示例:

import MessageStore from '../stores/MessageStore.js';
export default class Feed extends React.Component {
   constructor() {
      this.state = {messages: MessageStore.getAll()}
      //can I avoid writing this for every single method?
      this._onChange = this._onChange.bind(this); 
   }
   _onChange() {
       this.setState({messages: MessageStore.getAll()});
   };
   // componentDidMount, componentWillUnmount and render methods ommited
}

React中目前没有可激活的功能。这根本不是一种选择。

您可以对一个类进行后处理,并自动为每个函数bind,但在许多类中,这可能是不必要的,并且会给每个调用增加开销(因为您的代码可能会混合使用需要绑定的函数和不需要绑定的一些函数)。

您需要决定自动调整是否值得,或者在事件回调的上下文中仅使用bind语法(JavaScript中所需的典型位置)是否可以接受。

有一个使用优雅@decorator语法的新解决方案。你必须为Babel启用JavaScriptES2015 stage-0功能,但在那之后就轻而易举了!然后你可以写:

import autobind from 'autobind-decorator'
// (...)
<li onClick={ this.closeFeedback }>Close</li>
// (...)
@autobind
closeFeedback() {
  this.setState( { closed: true } );
}

要实现这一点,您需要安装一些构建库。方法如下:

npm install --save-dev babel-preset-stage-0
npm install --save-dev babel-plugin-react-transform
npm install --save-dev babel-plugin-transform-decorators-legacy
npm install --save-dev autobind-decorator

或者将它们全部封装在一个命令中:

npm install --save-dev babel-preset-stage-0 babel-plugin-react-transform babel-plugin-transform-decorators-legacy autobind-decorator

之后,根据您指定babel设置的位置更改.babelrcwebpack.config.js

query: {
  presets: ['es2015', 'react', 'stage-0'],
  plugins: [['transform-decorators-legacy']]
}

(注意,在.babelrc文件中,根节点从查询对象开始。)

祝你好运,别忘了进口声明!

如果您不想或还不能使用babel decorator语法。您可以定义一个自动绑定函数,并在类中添加一行锅炉板来处理自动绑定。

function autobind(target) { // <-- Define your autobind helper
    for (let prop of Object.getOwnPropertyNames(Object.getPrototypeOf(target))) {
        if (typeof target[prop] !== 'function') {
            continue;
        }
        if (~target[prop].toString().replace(/'s/g, '').search(`^${prop}[(][^)]*[)][{;]['''"]autobind['''"];`)) {
            target[prop] = target[prop].bind(target);
        }
    }
}
class Test {
    constructor() {
        autobind(this); // <- single line of boilerplate
        this.message = 'message';
    }
    method1(){ return this.method2(); }
    method2(){ console.log(this.message);}
    _handleClick() { 'autobind'; // <-- autobind searches for functions with 'autobind' as their first expression.
        console.log(this.message);
    }
}
let test = new Test();
let _handleClick = test._handleClick;
_handleClick();