我以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
并且一切正常。修改待办事项数据后,仅
重新渲染父项和已编辑的待办事项。
问题是,随着用户的滚动,我的列表有时会变得很大。并且,当更新单个待办事项时,渲染
父项,调用shouldComponentUpdate所有待办事项以及渲染单个待办事项所花费的时间越来越多。
如您所见,Todo组件具有与Todo数据不同的其他组件。这是所有待办事项渲染所需的数据并被共享(
例如,我们可以想象待办事项有一个“displayMode”)。具有许多属性会使shouldComponentUpdate
执行速度变慢。
此外,使用ReactCSSTransitionGroup
似乎有点过于慢下来,因为ReactCSSTransitionGroup
必须使自身
ReactCSSTransitionGroupChild
甚至在shouldComponentUpdate
的待办事项被调用。React.addons.Perf
显示ReactCSSTransitionGroup > ReactCSSTransitionGroupChild
对列表的每个项目都浪费了渲染时间。
因此,据我所知,我使用的PureRenderMixin
列表较大,但这可能还不够。我仍然表现不差,但是想知道是否有简单的方法可以优化我的渲染。
任何想法?
编辑:
到目前为止,我的大列表是分页的,因此,我没有大的项目列表,而是将这个大列表拆分为页面列表。
由于每个页面现在都可以实现,因此可以实现更好的性能shouldComponentUpdate。现在,当项目在页面中发生更改时,React只需调用在页面上迭代的主要render函数,而仅从单个页面调用render函数,这将减少迭代工作。
但是,我的渲染性能仍然与我拥有的页码(O(n))成线性关系。因此,如果我有成千上万的页面,仍然是一个问题:)在我的用例中,这不太可能发生,但我仍然对更好的解决方案感兴趣。
我很确定可以通过将大列表拆分成树(如持久数据结构)以及每个节点的位置来实现O(log(n))渲染性能,其中n是项目(或页面)的数量。有能力使计算短路shouldComponentUpdate
是的,我正在考虑类似于Scala或Clojure中的Vector之类的持久数据结构:
http://hypirion.com/imgs/pvec/9-annotated.png
但是我担心React,因为据我所知,渲染树的内部节点时可能必须创建中间dom节点。根据用例,这可能是一个问题(并可能在以后的React版本中解决)
同样,当我们使用Javascript时,我想知道Immutable-JS是否支持它,
并使“内部节点”可访问。参见:https ://github.com/facebook/immutable-js/issues/541
这是我使用ImmutableJS内部结构完成的POC实现。这不是公共API,因此尚未准备好进行生产,并且
当前无法处理特殊情况,但可以使用。
var ImmutableListRenderer = React.createClass({
render: function() {
// Should not require to use wrapper <span> here but impossible for now
return (<span>
{this.props.list._root ? <GnRenderer gn={this.props.list._root}/> : undefined}
{this.props.list._tail ? <GnRenderer gn={this.props.list._tail}/> : undefined}
</span>);
}
})
// "Gn" is the equivalent of the "internal node" of the persistent data structure schema of the question
var GnRenderer = React.createClass({
shouldComponentUpdate: function(nextProps) {
console.debug("should update?",(nextProps.gn !== this.props.gn));
return (nextProps.gn !== this.props.gn);
},
propTypes: {
gn: React.PropTypes.object.isRequired,
},
render: function() {
// Should not require to use wrapper <span> here but impossible for now
return (
<span>
{this.props.gn.array.map(function(gnItem,index) {
// TODO should check for Gn instead, because list items can be objects too...
var isGn = typeof gnItem === "object"
if ( isGn ) {
return <GnRenderer gn={gnItem}/>
} else {
// TODO should be able to customize the item rendering from outside
return <span>{" -> " + gnItem}</span>
}
}.bind(this))}
</span>
);
}
})
客户端代码看起来像
React.render(
<ImmutableListRenderer list={ImmutableList}/>,
document.getElementById('container')
);
这是一个JsFiddle ,它记录shouldComponentUpdate列表的单个元素(大小N)更新后的呼叫次数:这不需要调用N次shouldComponentUpdate
此ImmutableJs github 问题中共享了更多实现细节
本文向大家介绍react怎么提高列表渲染的性能?相关面试题,主要包含被问及react怎么提高列表渲染的性能?时的应答技巧和注意事项,需要的朋友参考一下 使用webpack 做代码分割。 使用hooks。
在上文中,我们从多个角度讨论了如何优化页面加载性能。但一个用户体验良好的页面,不仅要快速加载,还需要有一系列流畅的交互。从而,这一节我们把目光投向页面渲染性能。 渲染流程 浏览器在渲染页面前,首先会将 HTML 文本内容解析为 DOM,将 CSS 解析为 CSSOM。DOM 和 CSSOM 都是树状数据结构,两者相互独立,但又有相似之处。DOM 树描述了 HTML 标签的属性,以及标签之间的嵌套关
起因 问题的起因是左侧模版列表在开发时没有测试最多五百条数据的极限,当数据列表达到五百条的时候,就单纯的改变checkbox组件状态(选中或者不选中之间切换),就很慢,看了一下性能分析,一个click事件在4倍降低CPU的情况下长达4s的长任务,我不理解 :) 这里我在控制台中,发现列表并没有重新渲染所有节点,而且也没有接口调用。仅仅五百个节点就这样,虚拟dom性能有点... 顺便补充一下:rea
在项目运行时,渲染模块往往占据了最大的CPU开销,它也是我们为项目进行深度优化时最为关注的一部分。就目前而言,渲染性能主要被 不透明物体的渲染耗时 和 半透明物体的渲染耗时 所占据,而每一部分的性能开销又和其底层的渲染参数息息相关,比如 Draw Call数量、渲染面片数 和 可见蒙皮网格数 等等。因此,我们会根据上述性能参数对渲染模块进行详细的性能检测和分析。 数据汇总 该项主要展示项目运行过程
优化提升渲染性能,不仅能让页面更快的展现、可交互,同时能提升用户操作滚动的流畅度,对提升用户体验至关重要。 避免不必要的更新对比 Rax 同 React 一样,render 时会有 vdom 对比,如果对比发现 DOM 没有变化时,不会去真正更新页面。而本身 vdom 对比也是不小的消耗,你应该避免这种不必要的更新对比,使用 shouldComponentUpdate 方法明确标识你的组件什么时候
为了保障组件的性能, 我们有的时候会从组件渲染的角度出发. 更干净的render函数? 这个概念可能会有点让人疑惑. 其实在这里干净是指我们在shouldComponentUpdate这个生命周期函数里面去做浅比较, 从而避免不必要的渲染. 关于上面的干净渲染, 现有的一些实现包括React.PureComponent, PureRenderMixin, recompose/pure 等等. 第一