【发布时间】:2015-09-07 17:08:10
【问题描述】:
我举了一个 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 更新时,渲染父级需要越来越多的时间,在所有的 todo 上调用 shouldComponentUpdate,然后再渲染单个 todo。
如您所见,Todo 组件除了 Todo 数据之外还有其他组件。这是所有 todos 渲染所需的数据并且是共享的(例如,我们可以想象 todos 有一个“displayMode”)。拥有许多属性会使shouldComponentUpdate 的执行速度稍慢一些。
此外,使用ReactCSSTransitionGroup 似乎也慢了一点,因为ReactCSSTransitionGroup 必须呈现自己,ReactCSSTransitionGroupChild 甚至在调用 todos 的shouldComponentUpdate 之前。 React.addons.Perf 表明 ReactCSSTransitionGroup > ReactCSSTransitionGroupChild 渲染对于列表的每个项目都是浪费时间。
所以,据我所知,我使用PureRenderMixin,但如果列表更大,这可能还不够。我的表现仍然没有那么差,但想知道是否有简单的方法来优化我的渲染。
有什么想法吗?
编辑:
到目前为止,我的大列表是分页的,所以我现在将这个大列表拆分为一个页面列表,而不是一个大列表。这允许有更好的性能,因为每个页面现在都可以实现shouldComponentUpdate。现在当页面中的 item 发生变化时,React 只需要调用在页面上迭代的主渲染函数,并且只从单个页面调用渲染函数,这样可以大大减少迭代工作。
但是,我的渲染性能仍然与我拥有的页码 (O(n)) 成线性关系。因此,如果我有数千页,它仍然是同一个问题 :) 在我的用例中不太可能发生,但我仍然对更好的解决方案感兴趣。
我很确定可以通过将大列表拆分为树(如持久数据结构)来实现 O(log(n)) 渲染性能,其中 n 是项目(或页面)的数量,并且其中每个节点都有权使用shouldComponentUpdate 短路计算
是的,我正在考虑类似于持久数据结构的东西,例如 Scala 或 Clojure 中的 Vector:
但是我担心 React,因为据我所知,在渲染树的内部节点时,它可能必须创建中间 dom 节点。根据用例,这可能是一个问题(and may be solved in future versions of React)
此外,由于我们使用的是 Javascript,我想知道 Immutable-JS 是否支持这一点,并使“内部节点”可访问。见:https://github.com/facebook/immutable-js/issues/541
编辑:我的实验的有用链接:Can a React-Redux app really scale as well as, say Backbone? Even with reselect. On mobile
【问题讨论】:
-
首先我们需要定义“大”,然后我们需要意识到插入到 DOM 中的元素越多,我们的性能就会越慢。伴随着 CSS 过渡,您会预期整体性能会变慢。此外,PureRenderMixin 仅在您呈现的内容始终完全相同时才会起作用。
-
您是否在您的
Todos 上使用key属性? -
您会发现这很有用。 stackoverflow.com/questions/34983963/…
标签: javascript reactjs immutable.js