因此,我读完了this article,基本上讨论了v8和其他JavaScript引擎如何在内部缓存对象的“形状”,以便当他们需要重复访问对象上的特定属性时,可以使用直接内存地址,而不是查找该对象在该内存中的特定属性。
这让我开始思考,在React中,您经常在构造函数中声明组件的状态,但并不包括最终会包含在状态中的所有属性,例如:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
hasLoaded: false
};
}
componentDidMount() {
someAjaxRequest.then((response) => {
this.setState({
content: response.body,
hasLoaded: true
});
});
}
render() {
return this.state.hasLoaded ?
<div>{this.state.content}</div> :
<div>Loading...</div>;
}
}
由于根据本文所述,状态对象不会保持一致的结构,因此这样做比在构造函数中定义所有可能的状态字段效率低吗?您是否应该始终至少添加所有属性,甚至为其赋予值null
,以使对象始终保持一致? 这会对性能产生重大影响吗?
答案 0 :(得分:5)
TL; DR表现的提升似乎微不足道,以至于真的不值得。
测试设置:
我为这堂课赚了100,000个孩子:
import React, { Component } from 'react';
const getRand = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
class Child extends Component {
constructor() {
super();
this.state = {
loading: false,
};
}
componentDidMount() {
const key = getRand(1, this.props.numKeys);
this.setState({
key,
[key]: 'bar',
});
}
render() {
if (this.props.display) {
return <div>child {this.state.key} {this.state[this.state.key]}</div>
}
return <div>child 0</div>
}
}
export default Child;
孩子的构成如下:
const children = [];
for (let i = 0; i < 1 * 100 * 1000; i++) {
children.push(<Child display={true} numKeys={1000} key={i} />);
}
return (
<div>
{children}
</div>
);
想法是:我可以传入display
道具来为每个孩子呈现相同的HTML或不同的HTML。
我还传递了numKeys
来确定对象上应该有多少种不同类型的键。经过测试,display
道具并没有显着影响DOM渲染时间,因此我在下面没有进行报告。所有测试均通过yarn build && serve -s build
与create-react-app
一起运行
如您所见,在您拥有许多不同形状的对象之前,100,000个对象的性能可以忽略不计。即使这样,您在100,000个组件上的性能提升还是700ms,或者每个组件7微秒。当然不是声称的8倍加速。
更多:在任何现实的情况下,DOM操作可能会使您的渲染时间相形见and,而不是像此测试那样综合。
答案 1 :(得分:2)
除了进行优化之外,最好将所有本地状态字段建模,即使您提到的只是npm start -- --reset-cache
。这样,您可以通过简单调用rm -rf /tmp/haste-map-react-native-packager-*
将组件重置回其初始状态。
答案 2 :(得分:0)
为了优化和提高性能,始终建议在构造函数中初始化所有组件变量,以便在组件中加载初始值,并避免在运行时创建新的状态变量。
答案 3 :(得分:0)
预先定义所有属性的主要原因是,它充当组件的self documenting
功能。
所以
这样做的长期时间/维护收益将物有所值,不考虑性能收益。