Reactjs 防止react将未更改的组件呈现到虚拟DOM中
我已经用typescript编写了一个简单的treeview,使用react来呈现DOM 每个节点都必须遵循简单的界面Reactjs 防止react将未更改的组件呈现到虚拟DOM中,reactjs,Reactjs,我已经用typescript编写了一个简单的treeview,使用react来呈现DOM 每个节点都必须遵循简单的界面 interface INode { label: string; children: INode[]; } 然后通过以下方式描述该树: var tree = { label: "root", children: [ { label: "node 1", children: [
interface INode {
label: string;
children: INode[];
}
然后通过以下方式描述该树:
var tree = {
label: "root",
children: [
{
label: "node 1",
children: [
{
label: "node 1.0",
children: []
},
{
label: "node 1.1",
children: []
}
]
},
{
label: "node 2",
children: []
}
]
};
很简单。组件现在也非常简单。对于我拥有的节点:
class Node extends React.Component<INode, void>{
render() {
console.log(`Rendering ${this.props.label}`);
var list = this.props.children.map((node, i) => <li key={i}><Node {...node}/></li>);
return (
<div>
<span>{this.props.label}</span>
{this.props.children.length > 0 ? <ul>{list}</ul> : ""}
</div>
);
}
}
类节点扩展React.Component{
render(){
log(`Rendering${this.props.label}`);
var list=this.props.children.map((节点,i)=>);
返回(
{this.props.label}
{this.props.children.length>0?{list}
:“”
);
}
}
对于树的根,我使用状态而不是道具。但1秒钟后我刷新了状态。但国家本身并没有改变:
class Root extends React.Component<void, INode>{
constructor() {
super();
this.state = tree;
}
componentWillMount() {
setTimeout(() => {
this.setState((prevState: INode, props: void) => {
console.log(`Updating state of ${this.state.label}`);
return prevState;
});
}, 1000);
}
render() {
var list = this.state.children.map((node, i) => <li key={i}><Node {...node} /></li>);
return (
<div>
<span>{this.state.label}</span>
{this.state.children.length > 0 ? <ul>{list}</ul> : ""}
</div>
);
}
}
类根扩展React.Component{
构造函数(){
超级();
this.state=树;
}
组件willmount(){
设置超时(()=>{
this.setState((prevState:INode,props:void)=>{
log(`updateing state of${this.state.label}`);
返回状态;
});
}, 1000);
}
render(){
var list=this.state.children.map((node,i)=>);
返回(
{this.state.label}
{this.state.children.length>0?{list}
:“”
);
}
}
要运行此应用程序,只需以下代码行:
ReactDOM.render(
<Root/>,
document.getElementById("app")
);
ReactDOM.render(
,
document.getElementById(“应用程序”)
);
呈现的html看起来应该是这样的。我现在的问题是当我看到浏览器控制台时
渲染节点1
渲染节点1.0
渲染节点1.1
渲染节点2
更新根目录的状态
渲染节点1
渲染节点1.0
渲染节点1.1
渲染节点2
整个树被重新返回(进入虚拟DOM),而状态值和子级的道具没有改变
假设渲染过程非常复杂且耗时。是否有可能停止将孩子重新渲染到虚拟DOM中?提高ReactJS渲染性能
首先,除非您在应用程序中看到它的必要性,否则不要在这方面花费时间。检查虚拟DOM是一个非常便宜的操作。然而,如果你需要优化你的应用程序,有一些策略可以实现这一点
防止react将未更改的组件呈现到虚拟DOM中(如您所问)
有两种广泛的方法可以做到这一点:
- 不重新呈现将产生相同输出的组件
- 不将更改应用于组件,除非组件已更改
shouldComponentUpdate
更高效,您可以使用框架来确保您的状态中只有不可变的对象,或者您可以简单地养成不改变对象,而是创建新对象的习惯。看见这将允许您在将nextState和nextProps与当前状态和道具进行比较时进行浅层检查(可以很容易地使用)
不将非更改应用于组件
这意味着仅在新值与当前值不同时更新状态或道具。这种方法并没有经常提出,但我认为它值得一些借鉴
状态:如果newValue!==此.state.value
。这可以通过多种方式实现,但其中一种方式是在执行setState()
之前进行实际检查
道具:如果非更改来自道具,通常是因为父组件持有一个值(处于其状态),该值作为道具传递给它的另一个子组件。然后,父组件需要重新渲染自身及其所有子组件。如果您只想更改依赖于该值的组件,则可以让组件侦听全局应用程序状态的一部分,并仅注入对该组件有用的内容。这样,该值将直接传递给对其感兴趣的组件,而不会重新呈现其他组件
(在多个组件依赖同一数据的情况下,这样就不需要将状态存储在公共父组件中。除了提高效率外,这通常还可以更轻松地创建依赖现有应用程序状态某些部分的新组件。)
您可以使用,例如,维护全局应用程序状态。
,或者,列举一些选项
使用全局应用程序状态的另一个优点是,您可以执行检查(在应用程序状态处理程序中),以确保仅使用实际更改更新应用程序状态(即,如果与以前相同,则不设置值)
更小的组件:减少每次更改要重新渲染的DOM元素数量
另一种降低重新渲染成本的策略是使组件更小。然后,每个数据更改只应用于一小部分DOM,因为每个组件要渲染的元素更少
在我看来,您应该始终尝试这样做,因为除了性能方面,它还使您的代码更易于理解、重用和维护
选择策略
每种战术都可以单独使用,也可以结合使用,但应用第一组的两种战术通常不会比仅应用其中一种战术有显著的改进
我建议您从缩小组件开始,因为这也会给您带来其他优势,如上所述。不要为此烦恼。过早的优化是万恶之源。React设计用于处理极端情况,而且做得很好。当你达到极限时,再进行优化。出于好奇,检查
shouldCom