您应该在构造函数中定义组件状态的所有属性吗?
Should you define all properties of a component's state inside the constructor?
所以我读完了 this article,它基本上讨论了 v8 和其他 javascript 引擎如何在内部缓存对象的 "shape",以便当它们需要重复访问特定的 属性 在对象上,他们可以只使用直接内存地址,而不是查找特定 属性 在该对象内存中的位置。
这让我想到,在 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
的值,以便对象始终保持一致? 它会以任何实质性方式影响性能吗?
撇开优化不谈,对所有局部状态字段进行建模是一个好主意,即使它只是 data: null
正如您提到的那样。这样,您可以通过简单地调用 this.setState
.
将组件重置回其初始状态
TL;DR 性能提升似乎微不足道,不值得。
测试设置:
我赚了 100,000 children class:
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;
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
属性来为每个 child 呈现相同的 HTML,或者呈现不同的 HTML.
我还传入了一个numKeys
来确定object上应该有多少种不同类型的键。经过测试,display
属性并没有显着影响 DOM 渲染时间,所以我没有在下面报告。所有测试都是 运行 和 yarn build && serve -s build
通过 create-react-app
结果
所有 children
都使用相同的密钥
所有 children
3 个键
所有 children
10 个键
所有 children
1000 个密钥
中的所有测试
如您所见,100,000 objects 的性能可以忽略不计,除非您有很多不同形状的 objects。即便如此,您的性能提升还是超过 100,000 个组件 700 毫秒,或每个组件 7 微秒。这肯定不是声称的 8 倍加速。
此外:您的渲染时间可能会因 DOM 任何现实的动作而变得相形见绌,而不是像这个测试那样合成。
为了优化和更好的性能,始终建议在构造函数中初始化所有组件变量,以便组件加载初始值并避免在 运行 时创建新的状态变量。
预先定义所有属性的主要原因是它用作组件的 self documenting
功能。
所以
- 它减少了添加评论的需要
- 它减少了开发人员熟悉 him/herself 组件所需的时间
这样做的长期 time/maintenance 收益将收回成本,性能收益除外。
所以我读完了 this article,它基本上讨论了 v8 和其他 javascript 引擎如何在内部缓存对象的 "shape",以便当它们需要重复访问特定的 属性 在对象上,他们可以只使用直接内存地址,而不是查找特定 属性 在该对象内存中的位置。
这让我想到,在 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
的值,以便对象始终保持一致? 它会以任何实质性方式影响性能吗?
撇开优化不谈,对所有局部状态字段进行建模是一个好主意,即使它只是 data: null
正如您提到的那样。这样,您可以通过简单地调用 this.setState
.
TL;DR 性能提升似乎微不足道,不值得。
测试设置:
我赚了 100,000 children class:
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;
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
属性来为每个 child 呈现相同的 HTML,或者呈现不同的 HTML.
我还传入了一个numKeys
来确定object上应该有多少种不同类型的键。经过测试,display
属性并没有显着影响 DOM 渲染时间,所以我没有在下面报告。所有测试都是 运行 和 yarn build && serve -s build
通过 create-react-app
结果
所有 children
都使用相同的密钥所有 children
3 个键所有 children
10 个键所有 children
1000 个密钥 中的所有测试如您所见,100,000 objects 的性能可以忽略不计,除非您有很多不同形状的 objects。即便如此,您的性能提升还是超过 100,000 个组件 700 毫秒,或每个组件 7 微秒。这肯定不是声称的 8 倍加速。
此外:您的渲染时间可能会因 DOM 任何现实的动作而变得相形见绌,而不是像这个测试那样合成。
为了优化和更好的性能,始终建议在构造函数中初始化所有组件变量,以便组件加载初始值并避免在 运行 时创建新的状态变量。
预先定义所有属性的主要原因是它用作组件的 self documenting
功能。
所以
- 它减少了添加评论的需要
- 它减少了开发人员熟悉 him/herself 组件所需的时间
这样做的长期 time/maintenance 收益将收回成本,性能收益除外。