ReactJS. Assez lent lors du rendu et de la mise à jour d'une liste simple de 1500 <li> éléments. J'ai pensé VirtualDOM a été rapide

J'ai été vraiment déçu par la performance que j'ai sur le simple suivant ReactJS exemple. Lorsque vous cliquez sur un élément, l'étiquette (le comte) est mis à jour en conséquence. Malheureusement, cela prend à peu près ~0,5 à 1 seconde pour mise à jour. C'est principalement en raison de la "re-rendu de" l'ensemble de la liste des choses à faire.

Ma compréhension est que Réagir la clé de la conception de décision est de faire de l'API sembler comme il re-rend l'ensemble de l'application sur chaque mise à jour. Il est censé prendre en l'état actuel des DOM et de la comparer avec la cible DOM représentation, de faire une comparaison et de mise à jour uniquement les choses qui ont besoin de se faire jour.

Suis-je en train de faire quelque chose qui n'est pas optimal? Je pourrais toujours mettre à jour le décompte de l'étiquette manuellement (et de l'état en mode silencieux) et qui sera une quasi-instantanéité de l'opération, mais qui enlève le point de l'utilisation de ReactJS.

JS:

/** @jsx React.DOM */
TodoItem = React.createClass({
getDefaultProps: function () {
return {
completedCallback: function () {
console.log('not callback provided');
}
};
},
getInitialState: function () {
return this.props;
},
updateCompletedState: function () {
var isCompleted = !this.state.data.completed;
this.setState(_.extend(this.state.data, {
completed: isCompleted
}));
this.props.completedCallback(isCompleted);
},
render: function () {
var renderContext = this.state.data ?
(<li className={'todo-item' + (this.state.data.completed ? ' ' + 'strike-through' : '')}>
<input onClick={this.updateCompletedState} type="checkbox" checked={this.state.data.completed ? 'checked' : ''} />
<span onClick={this.updateCompletedState} className="description">{this.state.data.description}</span>
</li>) : null;
return renderContext;
}
});
var TodoList = React.createClass({
getInitialState: function () {
return {
todoItems: this.props.data.todoItems,
completedTodoItemsCount: 0
};
},
updateCount: function (isCompleted) {
this.setState(_.extend(this.state, {
completedTodoItemsCount: isCompleted ? this.state.completedTodoItemsCount + 1 : this.state.completedTodoItemsCount - 1
}));
},
render: function () {
var updateCount = this.updateCount;
return (
<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>
);
}
});
var data = {todoItems: []}, i = 0;
while(i++ < 1000) {
data.todoItems.push({description: 'Comment ' + i, completed: false});
}
React.renderComponent(<TodoList data={ data } />, document.body);

HTML:

<script src="http://fb.me/react-js-fiddle-integration.js"></script>

jsFiddle lien, juste au cas où: http://jsfiddle.net/9nrnz1qm/3/

  • Je reçois 0.13 s avec la production de construire, tout le meilleur pour vous?. Comparaison 4500 éléments prend un certain temps. La seule bonne des solutions impliquent pas rendu 1500 TodoItems, lorsque vous ne pouvez voir 100 au plus 🙂
  • Comment vérifiez-vous la performance (c'est à dire que vous avez obtenu 0.13 s)?
  • J'ai utilisé le générateur de profils dans les outils de dev. Il vous montre un montage de tous les JS exécution (assurez-vous qu'il est en mode Graphique, pas Lourde ou de l'Arbre). Après avoir cliqué sur une case il y a environ 130ms d'exécution du code. Voir ma réponse, en effet, il est allé vers le bas un peu.
  • Yeap.. le mien est autour de 150-170 ms
InformationsquelleAutor skay- | 2015-01-14