所以我正在努力学习反应,并在构造函数中理解.bind(this)
。但是我想我现在明白了,只是想知道为什么我会在onClick中使用它与箭头函数。请参阅以下代码:
绑定方法可确保eventClick函数中的“this”引用类
Class Click extends react.Component {
constructor(props) {
super(props)
this.clickEvent = this.clickEvent.bind(this);
}
render = () => (
<button onClick={this.clickEvent}>Click Me</button>
)
clickEvent() {console.log(this)} // 'this' refers to the class
}
但是这个方法也引用了这个类。是否有任何赞成使用一个与另一个相比?
Class Click extends react.Component {
render = () => (
<button onClick={() => {this.clickEvent()}}>Click Me</button>
)
clickEvent() {console.log(this)} // 'this' refers to the class
}
答案 0 :(得分:13)
您的第二个示例会在每个render
上重新创建该函数。在您的第一个中,您只需创建一次绑定函数。
您可以在构造函数中创建处理程序作为箭头函数:
class Click extends react.Component {
constructor(props) {
super(props)
this.clickEvent = () => { // ***
console.log(this); // ***
}; // ***
}
render = () => (
<button onClick={this.clickEvent}>Click Me</button>
)
}
使用class fields proposal syntax(在大多数React项目的转换程序设置中启用,以及您用于render
函数的那个),您可以这样写:
class Click extends react.Component {
constructor(props) {
super(props)
}
clickEvent = () => { // ***
console.log(this); // ***
}; // ***
render = () => (
<button onClick={this.clickEvent}>Click Me</button>
)
}
这是一回事。
附注:您正在为班级的每个实例创建单独的render
函数。没有必要这样做,它可以在原型上。所以:
class Click extends react.Component {
constructor(props) {
super(props)
}
clickEvent = () => {
console.log(this);
};
render() {
return <button onClick={this.clickEvent}>Click Me</button>;
}
}
答案 1 :(得分:1)
首先,让我们看一下每种技术的示例。
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>
}
}
在公共类字段上使用箭头功能更具可读性, 由于更少的代码行, 但是请记住,使用箭头功能会影响两件事:
首先是内存和性能;当您使用类字段定义函数时,整个方法都驻留在该类的每个实例上,而不是在原型上,而是使用 bind 技术, callback
存储在每个实例上,它调用存储在原型上的方法。
第二个可能受影响的是您编写单元测试的方式。 您将无法使用组件原型对以下函数调用进行存根:
const spy = jest.spyOn(MyComponent.prototype, 'clickHandler');
expect(spy).toHaveBeenCalled();
您将必须找到另一种方法来存根该方法,方法是通过传递道具中的间谍或检查状态更改。
计算机真的很擅长阅读代码;您不必为此担心。 您可能需要考虑使用类属性箭头功能使代码更易于阅读。
但是,如果要同时保持人类可读性和性能,请考虑使用plugin-transform-arrow-functions插件,只需运行npm i --save-dev @babel/plugin-transform-arrow-functions
并将其添加到“ babel.config.js
”或“ {{1}”中}”文件,例如:
.babelrc
您还可以使用类似auto-bind decorator的名称,将上面的示例转换为:
{
"presets": ["module:metro-react-native-babel-preset"],
"plugins": [
["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": false }],
["@babel/plugin-transform-arrow-functions", { "spec": true }]
]
}
注意:不必在每个函数上放置
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}