Реагируйте на производительность: рендеринг большого списка с PureRenderMixin
Я взял пример TodoList, чтобы отразить мою проблему, но, очевидно, мой реальный код более сложен.
У меня есть такой псевдокод, как этот.
var Todo = React.createClass({
mixins: [PureRenderMixin],
............
}
var TodosContainer = React.createClass({
mixins: [PureRenderMixin],
renderTodo: function(todo) {
return <Todo key={todo.id} todoData={todo} x={this.props.x} y={this.props.y} .../>;
},
render: function() {
var todos = this.props.todos.map(this.renderTodo)
return (
<ReactCSSTransitionGroup transitionName="transition-todo">
{todos}
</ReactCSSTransitionGroup>,
);
}
});
Все мои данные неизменны, и PureRenderMixin используется надлежащим образом, и все работает отлично. Когда данные Todo изменены, только родитель и отредактированный todo перерисовываются.
Проблема в том, что в какой-то момент мой список увеличивается по мере прокрутки пользователем. И когда обновляется один Todo, рендеринг родителя занимает все больше и больше времени,shouldComponentUpdate
на всех задачах, а затем визуализировать единственную задачу.
Как видите, компонент Todo имеет другой компонент, нежели данные Todo. Это данные, которые требуются для рендеринга всеми задачами и являются общими (например, мы можем представить, что для задач есть «displayMode»). Наличие многих свойств делаетshouldComponentUpdate
выполнять немного медленнее.
Кроме того, используяReactCSSTransitionGroup
кажется, немного замедляется, так какReactCSSTransitionGroup
должны сделать себя иReactCSSTransitionGroupChild
еще доshouldComponentUpdate
из todos называется.React.addons.Perf
показывает, чтоReactCSSTransitionGroup > ReactCSSTransitionGroupChild
рендеринг - это потеря времени на каждый элемент списка.
Итак, насколько я знаю, я используюPureRenderMixin
но с большим списком этого может быть недостаточно. Я все еще получаю неплохие результаты, но хотел бы знать, есть ли простые способы оптимизировать мой рендеринг.
Любая идея?
редактировать:
Пока что мой большой список разбит на страницы, поэтому вместо большого списка элементов я теперь разбил этот большой список на список страниц. Это позволяет повысить производительность, поскольку каждая страница теперь может быть реализована.shouldComponentUpdate
, Теперь, когда элемент изменяется на странице, React должен только вызывать основную функцию рендеринга, которая выполняет итерацию на странице, и вызывать функцию рендеринга только с одной страницы, что делает работу итераций намного меньше.
Тем не менее, моя производительность рендеринга по-прежнему линейна по отношению к номеру страницы (O (n)) у меня есть. Так что, если у меня есть тысячи страниц, это все та же проблема :) В моем случае это вряд ли произойдет, но я все еще заинтересован в лучшем решении.
Я почти уверен, что можно добиться производительности рендеринга O (log (n)), где n - это количество элементов (или страниц), разделив большой список на дерево (например, постоянную структуру данных), и где каждый узел имеет право замыкать вычисления сshouldComponentUpdate
Да, я думаю о чем-то похожем на постоянные структуры данных, такие как Vector в Scala или Clojure:
Однако меня беспокоит React, потому что, насколько я знаю, возможно, придется создавать промежуточные dom-узлы при рендеринге внутренних узлов дерева. Это может быть проблемой в зависимости от варианта использования (и может быть решена в будущих версиях React)
Также, поскольку мы используем Javascript, мне интересно, поддерживает ли Immutable-JS это, и делает ли «внутренние узлы» доступными. Увидеть:https://github.com/facebook/immutable-js/issues/541
редактироватьполезная ссылка с моими экспериментами:Может ли приложение React-Redux действительно масштабироваться так же, как, скажем, Backbone? Даже с повторным выбором. На мобильный