当我感到手工功能/对象绑定以及与范围相关的问题令人头疼之后,我开始使用箭头功能,但是非常有意思的是,我开始知道使用正常功能(ES5)比使用箭头功能(ES6)更好。
我对这些功能的理解
React中的正常功能:
- 手动绑定对象/功能,以便在功能内部玩状态或道具并避免与范围相关的问题
- 总是在构造函数中绑定对象/函数,而不是直接在渲染中绑定
- 如果在构造函数中执行此操作,则Webpack仅在组件首次呈现时在bundle.js文件中创建一次新的对象/函数
- 如果直接在渲染中进行操作,则每次组件渲染并重新渲染时,Webpack都会在bundle.js文件中创建一个新的对象/函数
- 如果您不绑定,则无法访问状态或道具。您必须将当前对象分配给局部变量,否则this.state或this.props未定义
React中的箭头功能:
- 无需在构造函数中绑定对象/函数也无需渲染
- 您无需依赖当前对象的局部变量项,即让它= this;
- 您将不会遇到范围问题,并且对象/函数绑定会自动出现
但是我的询问是,我听说建议使用常规函数并将其绑定到构造函数中,而不要使用箭头函数,因为每次组件渲染和重新渲染时,箭头函数都会在Webpack bundle.js中创建新的对象/函数。
这是真的吗?推荐哪个?
此线程接受的答案Correct use of arrow functions in React说—>这取决于您在哪里使用Arrow函数。如果在render方法中使用Arrow函数,那么每次调用render时,它们都会创建一个新实例,就像绑定如何工作一样。
很抱歉,如果您觉得这是一个戏剧问题,但这是我最大的疑问。请建议
答案 0 :(得分:6)
那里有很多答案,但人们总是感到困惑。我知道这一点是因为我前一段时间感到困惑。一段时间后,我掌握了这些概念。
- 手动绑定对象/功能,以便与状态或道具一起玩 函数内部,并避免与范围相关的问题
并非完全正确。您无需绑定功能即可与状态或道具一起玩。当您在合并范围中失去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不是这样做的,您的App是。
- 如果您不绑定,则无法访问状态或道具。您必须将当前对象分配给局部变量,否则this.state或 this.props未定义
同样,如果您在类范围内使用函数,则不必绑定它。如果在类之外使用此函数(例如按钮回调),则必须将其绑定。这与state
或props
不相关。这与使用this
有关。
用于绑定的第二个选项是使用常规函数在构造函数中进行绑定,而第三个选项是使用无绑定的箭头函数。
现在,箭头功能。
1。无需在构造函数中绑定对象/函数也无需渲染
是的
- 您无需依赖当前对象的局部变量项,即让它= this;
是的
- 您将不会遇到范围问题,并且对象/函数绑定会自动出现
是的
但我的查询是我听说建议使用常规 函数并将其绑定到构造函数中,而不是使用箭头函数 因为箭头函数会在Webpack中创建新的对象/函数 每次您的组件渲染和重新渲染时,bundle.js。
就像每个人所说的那样,这取决于您在哪里使用它们。
render() {
return (
<div>
<button onClick={() => this.aFunction()}>Click</button>
</div>
);
}
在这里,它将在每个渲染中重新创建。但是,如果您不需要传递任何参数,则可以通过引用使用它。
render() {
return (
<div>
<button onClick={this.aFunction}>Click</button>
</div>
);
}
与上一个相同。因此,如果在渲染方法中看到()
,则在每个渲染中都会重新创建此函数。常规或箭头一无所谓。如果您以某种方式调用它,那么您正在重新创建它。这适用于像aFunction.bind(this)
这样的渲染中绑定。我在那里看到()
。
因此,请通过引用使用函数,以避免出现此问题。现在,最大的问题是,当我们需要一些论点时会发生什么?如果使用箭头函数传递参数,请尝试更改逻辑。
但这真的很重要吗?就像@Eric Kim所说的那样,如果您确实需要优化,则是一个问题。这是一个普遍的建议,因为我已经从很多人那里听到过。但就我个人而言,如果要在每个渲染器中重新创建函数,我会尽量避免使用它们。再次,这完全是个人的。
如何更改逻辑?您正在映射具有项的数组并创建 一个按钮。在此按钮中,您正在使用一个将项目名称传递给函数的函数。
{
items.map( item =>
<button onClick={() => this.aFunction(item.name)}>Click</button>
)
}
此功能将在每个渲染器的每个项目中重新创建!因此,更改逻辑,创建一个单独的Item
组件并进行映射。通过item
,aFunction
作为道具。然后在该组件中使用处理程序函数,即可使用您的函数。
const Item = ( props ) => {
const handleClick = () => props.aFunction( props.item.name );
return (
<button onClick={handleClick}>Click</button>
);
}
在这里,您正在使用带有其引用的onClick
处理程序,它将调用您的真实函数。在每个渲染中均不会重新创建任何功能。但是,缺点是,您需要编写一个单独的组件和更多代码。
您通常可以应用此逻辑。也许会有一些你不知道的例子,谁知道。因此,决定权由您决定。
顺便说一句,@ widged在评论中给出的中型帖子是有关此问题的著名讨论。箭头功能真的比常规功能慢吗?是。但是多少钱?我猜没有那么多。同样,对于已编译的代码也是如此。将来,当它们变得原生时,它们将成为更快的。
作为个人说明。自从我喜欢箭头功能以来,我一直都在使用它们。但是不久前在讨论中,有人说
当我在课堂上看到箭头功能时,我认为:'此功能 在此类之外被使用/调用”。如果我看到一个普通的我 了解此函数在类内部调用。
我真的很喜欢这种方法,现在,如果不需要在类之外调用函数,我将使用常规方法。
答案 1 :(得分:1)
如果您具有以下React代码,则
class A extends React.Component {
constructor(props) {
super(props)
this.state = {name: props.name}
}
render() {
return (
<button onclick={(event)=>console.log(this.state.name)} />
)
}
}
更改为关注
class A extends React.Component {
state = {name: this.props.name}
render() {
return (
<button onclick={this.logName} />
)
}
logName = (event) => {
console.log(this.state.name)
}
}
这样,您就不会在每个渲染器上都创建新的匿名函数。
每次运行代码时都会创建新的函数实例
()=>
,这不是magic
。看看以下成员函数
class A {
memberFuncWithBinding = () => {}
memberFuncWithoutBinding(){}
}
实例化类时,这两个成员函数仅创建一次。再说一次,没有魔术,而是上级成员函数是首选,因为在该函数中使用this
时,您将具有正确的A类绑定。
编辑:看,在遇到问题之前,请勿尝试优化代码。创建新函数时,每个渲染速度都较慢,但只有毫秒级。