首先,让我们从每种技术的示例开始!
但这种差异更多地与JavaScript
语言本身有关。
捆绑:
import React from 'react';
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.clickHandler = this.clickHandler.bind(this);
}
clickHandler() {
console.log( this )
}
render() {
return <button onClick={this.clickHandler}>Click Me</button>
}
}
箭头功能:
import React from 'react';
class MyComponent extends React.Component {
constructor(props) {
super(props)
}
clickHandler = () => {
console.log( this )
}
render() {
return <button onClick={this.clickHandler}>Click Me</button>
}
}
优点和缺点:
在 public-class-field 上使用 Arrow-function 更易于人类阅读,因为代码行更少,但请记住,使用 Arrow-function 会影响两件事:
首先是 内存和性能;当您使用类字段定义函数时,您的整个方法驻留在 类的每个实例上, 而不是在原型上,但是使用 绑定技术,callback
每个实例上只存储一小部分,它调用存储在原型。
可能受到影响的第二件事是您如何编写单元测试。您将无法使用组件原型来存根如下函数调用:
const spy = jest.spyOn(MyComponent.prototype, 'clickHandler');
// ...
expect(spy).toHaveBeenCalled();
必须找到另一种方法来存根该方法,例如,通过 传入 spyprops
或 检查state
更改。
结论
计算机非常擅长阅读代码;你不应该担心这个。您可能需要考虑通过使用类属性箭头函数使您的代码更具人类可读性。
其他工具:
如果您想保持人类可读性和性能,请考虑使用plugin-transform-arrow-functions插件(尽管对我v7.2.0
造成了问题),只需运行npm i --save-dev @babel/plugin-transform-arrow-functions
并将其添加到您的“ babel.config.js
”或“ .babelrc
”文件中,例如:
{
"presets": ["module:metro-react-native-babel-preset"],
"plugins": [
["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": false }],
["@babel/plugin-transform-arrow-functions", { "spec": true }]
]
}
或者你可以使用类似auto-bind 装饰器的东西,它会将上面的例子变成:
import React from 'react';
import { boundMethod as bind } from 'autobind-decorator';
class MyComponent extends React.Component {
constructor(props) {
super(props)
}
@bind
clickHandler() {
console.log( this )
}
render() {
return <button onClick={this.clickHandler}>Click Me</button>
}
}
请注意,没有必要将@bind
每个功能都放在上面。你只需要绑定你传递的函数。例如onClick={this.doSomething}
或fetch.then(this.handleDone)