【发布时间】:2023-03-16 23:00:02
【问题描述】:
问题
*这不完全是我的情况,但重要的是这里。
想象一个呈现元素列表的应用:
const ElementsList = ({elements, <onElementTextChange>}) => (
<div className='ElementsList'>
{elements.map(el => (
<Element
key={el.id}
element={el}
/>
))}
</div>
)
元素保持在呈现ElementsList 的父组件的状态。每个元素都是一个简单的对象:
this.state = {elements: [
{id: 1, text: 'apple'},
{id: 23, text: 'banana'},
]}
...
render() { ... <ElementsList elements={this.state.elements}/> ... }
每个元素都使用附近的输入字段进行渲染以更改其文本:
export const Element = ({element, <onTextChange>}) => (
<div className='Element'>
<div className='element-text'>{element.text}</div>
<input type='text' value={element.text} onChange={???}></input>
</div>
)
考虑到可能有很多元素(应用程序可以处理的越多越好)。
现在的问题是我们应该如何通过这些输入来更新文本。
解决方案
我看到 2 个选项(它们的一些组合是可能的):
1。正确的反应方式(是吗?) - 通知父组件有关更改
- 在元素:
onChange={evt => onTextChange(evt.target.value)} - 在 ElementsList:
onTextChange={newText => onElementTextChange(el, newText)} - 在父组件处:
onElementTextChange={ (element, newText) => {make new elements array with the updated element somehow; setState(elements)} }
该解决方案似乎难以实施。与下面的替代方案相比,它也很慢。输入更改时发生的事件(如果我错了,请纠正我):
- 通过组件链通知父组件有关更改
- 父组件构造新元素数组并调用
setState - 整个虚拟 DOM 得到更新(包括每个元素)
- 更新的虚拟 DOM 与之前的虚拟 DOM 版本进行比较
- 一个元素在真实 DOM 中更新
2。直接更新 Element 的 props 和 forceUpdate()
- 将 Element 重写为类而不是功能组件
- 在元素处:onChange={evt => {element.text = evt.target.value; this.forceUpdate()}}
输入更改时发生的事件:
- props.element.text 被改变,
forceUpdate被调用 - 仅更新虚拟 DOM 中的一个元素
- 将虚拟 DOM(一个元素)的更新子树与旧虚拟 DOM 进行比较
- 一个元素在真实 DOM 中更新
问题
目前我正在使用一种中间方法,但更多的是在“适当的反应方式”方面。而且速度还不够快。
我更喜欢第二个选项,它需要的代码更少,而且看起来应该运行得更快(理论上)。
- 使用第二种方法会显着提高性能吗? (记住有成千上万的元素)
- 这种方法会导致哪些具体问题?是的,是的,我知道代码不那么透明,这不是它的本意。
- 您还有其他提高性能的方法吗?我很乐意尝试更少的类似 react 的建议,可能会考虑部分或完全放弃 react。
【问题讨论】:
-
我会使用选项 2,但我不确定如何回答您的问题。为了衡量性能,React 刚刚引入了profiler,因此您可以同时尝试两者,看看性能影响是什么。
-
@Toby 谢谢。我会尝试测量性能
标签: javascript reactjs react-props react-lifecycle react-state-management