javascript - 如何决定在 React 中调用处理函数的最有效方式?
问题描述
我对 React 还是很陌生,但我意识到定义回调函数有两种常见的方法:
// Method 1
private handleInputChange = (event) => {
this.setState({name: event.target.value});
}
// Method 2
private handleInputChange(event){
this.setState({name:event.target.value});
}
在 DOM 元素内部(对于这个例子,让我们使用<input>
),可以通过不同的方法调用处理程序,例如:
// Method 1
<input
type="text"
onChange={this.handleInputChange}
/>
// Method 2
<input
type="text"
onChange={(e) => this.handleInputChange(e)}
/>
// Method 3 (assume the function don't have parameters)
<input
type="text"
onChange={this.handleNewThing()}
/>
我的问题是,使用哪种方法合适?我真的对所有这些方法感到困惑。然后我看到人们bind()
出于某种原因包括在内?
解决方案
你是对的,有很多方法可以处理处理程序(ba-dum-tss)。React 已经存在了一段时间,而 JavaScript 的面貌在那段时间发生了很大变化。
在 React 文档中有一整页是关于处理事件的,但是这里有一些处理回调的方式的比较:
class MyComponent extends React.Component {
constructor (props) {
super(props)
this.boundHandleClick = this.boundHandleClick.bind(this)
}
arrowHandleClick = (event) => { this.props.onClick(event.target.id) }
boundHandleClick (event) { this.props.onClick(event.target.id) }
boundInRenderHandleClick (event) { this.props.onClick(event.target.id) }
unboundHandleClick (event) { this.props.onClick(event.target.id) }
render () {
return (
<div>
<button id='zero' onClick={(event) => { this.props.onClick(event.target.id) }} />
<button id='one' onClick={arrowHandleClick} />
<button id='two' onClick={boundHandleClick} />
<button id='three' onClick={boundInRenderHandleClick.bind(this)} />
<button id='four' onClick={unboundHandleClick} />
</div>
)
}
}
点击时:
#zero
会正确调用props.onClick
. 这样做的问题是,在渲染方法中创建的匿名函数将在每次渲染时重新创建。这对性能不利。#one
会正确调用props.onClick
. 因为回调被定义为类方法,所以它只会在MyComponent
实例化(和挂载)时创建。这是定义回调的可接受方式。显然它比以前想象的要慢,但在我看来它也是最整洁的。#two
会正确调用props.onClick
. 这与 基本相同arrowHandleClick
,只是它是绑定函数而不是箭头函数。出于所有意图和目的,它们是相同的 -但无论如何都要挖掘差异。#three
将正确调用props.onClick
,结果与 相同#two
,但对性能有负面影响,因为#zero
不应在 render 方法中创建或绑定函数。#four
将无法正常工作并会引发错误。当它运行时,this
将引用元素(在本例中为#four
)而不是类实例。在所有其他处理程序中,this
指的是 React 类实例,它有一个props.onClick
.
现在有一种新的可接受的编写组件的方式:使用普通函数和钩子。this
已成为过去。
const MyComponent = (props) => {
const handleClick = event => props.handleClick(event.target.id)
const memoizedHandleClick = React.useCallback(
event => props.handleClick(event.target.id),
[props.handleClick]
)
return (
<div>
<button id='zero' onClick={event => props.handleClick(event.target.id)} />
<button id='one' onClick={handleClick} />
<button id='two' onClick={memoizedHandleClick} />
</div>
)
}
所有回调在这里都能正常工作——唯一的区别是memoizedHandleClick
不会在每次渲染时重新创建,除非props.handleClick
发生变化。根据我自己的经验,两者都是可以接受的,人们似乎不再介意在功能组件中重新创建回调 - 而是在遇到它们时务实并解决性能问题。
推荐阅读
- reactjs - 'npm run build'(弹出的项目有 SCSS 加载器)错误
- c# - .NET Core 2.0 WebAPI 与 MySQL DB - dotnet publish - 运行 .dll 时连接字符串为空
- java - 使用 Retrofit 选择某个 ID
- java - 请帮助我解决这个错误,试图在 mysql 中创建数据库
- node.js - 尝试在 Mlab 上连接到 MongoDB 时出错
- opencv - 'copyTo' 处的断言失败错误。检查图像大小和类型
- python - 独角兽 | Selenium - 消息:无法找到一组匹配的功能
- javascript - Selenium 从没有 ID 的菜单中获取元素
- python - Chrome 崩溃了,jupyter notebook 还在运行吗?
- python - 如何确保 python 包模块将结果保存到该包的子目录?