那里有很多答案,但人们总是感到困惑。我知道这一点是因为我不久前感到困惑。一段时间后,我掌握了这些概念。
- 手动绑定对象/函数,以便在函数内部使用 state 或 props 并避免与作用域相关的问题
不完全正确。您不需要绑定函数来使用 state 或 props。this
当您this
在范围内丢失上下文时,您可以将函数绑定到。例如在回调函数中。
class App extends React.Component {
state = {
name: "foo",
}
aFunction() {
console.log( this.state.name );
}
render() {
return <div>{this.aFunction()}</div>;
}
}
你不需要绑定你的函数,因为this
你指向你的类并且你不会丢失它的上下文。但是如果你在回调中像按钮一样使用你的函数,你必须绑定它:
class App extends React.Component {
state = {
name: "foo",
}
aFunction() {
console.log( this.state.name );
}
render() {
return (
<div>
<button onClick={this.aFunction}>Click</button>
</div>
);
}
}
这不起作用,因为您失去了上下文。现在,您需要以某种方式恢复其上下文,对吗?好的,让我们看看如何做到这一点。首先,我想在按钮回调中绑定它。
<button onClick={this.aFunction.bind(this)}>Click</button>
是的,这有效。但是,它将在每次渲染中重新创建。所以:
- 始终在构造函数中绑定对象/函数,但不直接在渲染中绑定
是的。不要像我上面那样绑定它,在你的构造函数中进行。
如果你在构造函数中这样做,那么当你的组件第一次渲染时,Webpack 只会在 bundle.js 文件中创建一次新的对象/函数
如果你直接在渲染中执行,那么每次你的组件渲染和重新渲染时,Webpack 都会在 bundle.js 文件中创建一个新的对象/函数
你在这里总结了我迄今为止试图解释的内容。但是,我认为 Webpack 不是这样做的,您的应用程序是。
- 如果不绑定,则无法访问状态或props。您必须将当前对象分配给局部变量,否则 this.state 或 this.props 未定义
同样,如果您在类范围内使用您的函数,则不必绑定它。如果你在你的类之外使用这个函数,比如按钮回调,你必须绑定它。这与state
或无关props
。这与使用this
.
绑定的第二个选项是使用常规函数在构造函数中进行绑定,第三个选项是使用没有绑定的箭头函数。
现在,箭头功能。
1.不需要在构造函数中绑定对象/函数也不需要渲染
是的。
- 您无需依赖当前对象的局部变量,即让 that = this;
是的。
- 你不会有范围问题,对象/函数绑定会自动执行
是的。
但我的疑问是,我听说建议使用普通函数并将其绑定在构造函数中,而不是使用箭头函数,因为每次组件渲染和重新渲染时,箭头函数都会在 Webpack bundle.js 中创建新的对象/函数。
就像大家说的,这取决于你在哪里使用它们。
render() {
return (
<div>
<button onClick={() => this.aFunction()}>Click</button>
</div>
);
}
在这里,它将在每次渲染中重新创建。但是,如果您不需要向它传递任何参数,则可以通过引用使用它。
render() {
return (
<div>
<button onClick={this.aFunction}>Click</button>
</div>
);
}
这与上一个相同。因此,如果您()
在渲染方法中看到 a ,则该函数会在每次渲染中重新创建。常规或箭头一个,都没有关系。如果您以某种方式调用它,那么您就是在重新创建它。这适用于渲染中的绑定,如aFunction.bind(this)
。我看到()
那里。
因此,通过引用使用函数可以避免此问题。现在,最大的问题是当我们需要一些参数时会发生什么?如果您使用箭头函数传递参数,请尝试更改您的逻辑。
但这真的那么重要吗?就像@Eric Kim 所说的那样,如果你真的需要优化,优化是一个问题。这是一个普遍的建议,因为我从很多人那里听到了这个建议。但就我个人而言,如果函数会在每次渲染中重新创建,我会尽量避免使用它们。但同样,这完全是个人的。
你怎么能改变你的逻辑?您正在使用项目映射数组并创建按钮。在此按钮中,您使用的是将项目名称传递给函数的函数。
{
items.map( item =>
<button onClick={() => this.aFunction(item.name)}>Click</button>
)
}
此功能将在每个项目的每次渲染中重新创建!所以,改变你的逻辑,创建一个单独的Item
组件并映射它。通过item
,aFunction
作为props。然后在此组件中使用处理程序函数使用您的函数。
const Item = ( props ) => {
const handleClick = () => props.aFunction( props.item.name );
return (
<button onClick={handleClick}>Click</button>
);
}
在这里,您使用的是onClick
带有引用的处理程序,它会调用您的真实函数。不会在每次渲染中重新创建任何功能。但是,不利的一面是,您需要编写一个单独的组件和更多的代码。
大多数情况下,您可以应用此逻辑。也许会有一些你做不到的例子,谁知道呢。所以决定权在你。
顺便说一下,@widged 在评论中给出的 Medium 帖子是关于这个问题的著名讨论。箭头函数真的比普通函数慢吗?是的。但是多少钱?我猜没有那么多。此外,对于转译的代码也是如此。将来当他们成为本地人时,他们将成为更快的人。
作为个人的旁注。自从我喜欢它们以来,我一直在使用箭头函数。但是前段时间在讨论中,有人说
当我在类中看到一个箭头函数时,我认为:“这个函数正在这个类之外被使用/调用”。如果我看到一个普通的,我就会明白这个函数是在类内部调用的。
我真的很喜欢这种方法,现在如果我不需要在课外调用我的函数,我会使用常规方法。