Javascript ReactJS。渲染和更新1500个简单列表时速度非常慢<;李>;元素。我觉得VirtualDOM很快
我对下面这个简单的例子的性能感到非常失望。单击项目时,标签(计数)会相应更新。不幸的是,这大约需要0.5-1秒才能得到更新。这主要是因为“重新呈现”了整个待办事项列表 我的理解是React的关键设计决策是让API看起来像是每次更新都会重新呈现整个应用程序。它应该获取DOM的当前状态,并将其与目标DOM表示进行比较,进行区分并仅更新需要更新的内容 我是否在做一些非最佳的事情?我总是可以手动更新计数标签(并以静默方式更新状态),这几乎是一个即时操作,但这就失去了使用ReactJS的意义Javascript ReactJS。渲染和更新1500个简单列表时速度非常慢<;李>;元素。我觉得VirtualDOM很快,javascript,performance,dom,reactjs,Javascript,Performance,Dom,Reactjs,我对下面这个简单的例子的性能感到非常失望。单击项目时,标签(计数)会相应更新。不幸的是,这大约需要0.5-1秒才能得到更新。这主要是因为“重新呈现”了整个待办事项列表 我的理解是React的关键设计决策是让API看起来像是每次更新都会重新呈现整个应用程序。它应该获取DOM的当前状态,并将其与目标DOM表示进行比较,进行区分并仅更新需要更新的内容 我是否在做一些非最佳的事情?我总是可以手动更新计数标签(并以静默方式更新状态),这几乎是一个即时操作,但这就失去了使用ReactJS的意义 /**@j
/**@jsx React.DOM*/
TodoItem=React.createClass({
getDefaultProps:函数(){
返回{
completedCallback:函数(){
log(“未提供回调”);
}
};
},
getInitialState:函数(){
归还这个道具;
},
updateCompletedState:函数(){
var isCompleted=!this.state.data.completed;
this.setState(u.extend)(this.state.data{
已完成:已完成
}));
this.props.completedCallback(isCompleted);
},
渲染:函数(){
var renderContext=this.state.data?
(
{this.state.data.description}
):空;
返回renderContext;
}
});
var TodoList=React.createClass({
getInitialState:函数(){
返回{
todoItems:this.props.data.todoItems,
已完成的待办事项:0
};
},
updateCount:函数(已完成){
this.setState(u.extend)(this.state{
CompletedToDoitemScunt:isCompleted?this.state.CompletedToDoitemScunt+1:this.state.CompletedToDoitemScunt-1
}));
},
渲染:函数(){
var updateCount=this.updateCount;
返回(
计数:{this.state.completedToDoItemsCunt}
{this.state.todoItems.map(函数(todoItem)){
返回
}) }
);
}
});
var data={todoItems:[]},i=0;
而(i++<1000){
push({description:'Comment'+i,completed:false});
}
React.renderComponent(,document.body)代码>
当您生成元素列表时,您应该为每个人提供唯一的关键道具。就你而言:
<ul className="todo-list">
{ this.state.todoItems.map(function (todoItem, i) {
return <TodoItem key={i} data={ todoItem } completedCallback={ updateCount } />
}) }
</ul>
您正在进行一些字符串连接以设置正确的类名
。要获得更具可读性的代码,请尝试使用nice和simple:
render:function(){
var renderContext=this.state.data?
var cx=React.addons.classSet({
“待办事项”:true,
“穿透”:this.state.data.completed
});
(
{this.state.data.description}
):空;
返回renderContext;
}
如果你做到以下几点,你可以大大缩短时间。它花了25到45毫秒为我更新
- 使用生产构建
- 实现shouldComponentUpdate
- 不可变地更新状态
updateCompletedState:函数(事件){
var isCompleted=event.target.checked;
此.setState({数据:
_.extend({},this.state.data{
已完成:已完成
})
});
this.props.completedCallback(isCompleted);
},
shouldComponentUpdate:函数(nextProps,nextState){
返回nextState.data.completed!==this.state.data.completed;
},
(daniula指出,这段代码有很多值得怀疑的地方)我正在查看列表的呈现位置()
<div>
<div>count: {this.state.completedTodoItemsCount}</div>
<ul className="todo-list">
{ this.state.todoItems.map(function (todoItem) {
return <TodoItem data={ todoItem } completedCallback={ updateCount } />
}) }
</ul>
</div>
然后,只需在更改后重新提交一个TodoItem,如下所示:
ReactDOM.render(<TodoItem ...>, document.getElementById('someindex'));
ReactDOM.render(,document.getElementById('someindex');
ReactJS应该是快速的,是的,但是您仍然需要坚持通用编程范式,即要求机器尽可能少地执行操作,从而尽可能快地生成结果。重新渲染那些不需要重新渲染的内容会阻碍这一点,无论这是否是“最佳实践”。我在制作版本中得到了0.13秒。区分4500个元素需要一些时间。这里唯一好的解决方案是不渲染1500个TodoItems,而最多只能看到100个:-)如何检查性能(即获得0.13秒)?我在开发工具中使用了探查器。它向您显示所有JS执行的时间线(确保它处于图表模式,而不是繁重或树形)。单击复选框后,代码执行时间约为130ms。看我的答案,它实际上下降了不少。是的。。我的是150-170msSo,这实际上意味着当TodoList被“重新渲染”时,如果TodoItem的状态不变,它将不会被“重新渲染”?正确。这意味着react不需要调用TodoItem的render,也不需要在父级更新时区分li、input和span。这意味着如果TodoItem有多个状态,即完成、部分完成等,并且应用了不同的样式,则必须检查shouldComponentUpdate函数中的所有状态。这不正是React自动检查的理想选择吗?是的,或者如果下一个状态和当前状态存在对象,您可以做一个粗略的比较。React提供了一种实现这种shouldComponentUpdate的方法,但它在默认情况下并没有启用,并且它对props和state进行了粗略的比较
<div>
<div>count: {this.state.completedTodoItemsCount}</div>
<ul className="todo-list">
{ this.state.todoItems.map(function (todoItem) {
return <TodoItem data={ todoItem } completedCallback={ updateCount } />
}) }
</ul>
</div>
return <div id={someindex++}><TodoItem
data={ todoItem }
completedCallback={ updateCount }
/></div>
ReactDOM.render(<TodoItem ...>, document.getElementById('someindex'));