Skip to content

react-tiny-virtual-list源码阅读 #24

Open
@RachelRen

Description

@RachelRen

最近在研究react的性能相关的问题,就学习了一下react-virtualized, 也顺便看了一下react-tiny-virtual-list的源码。然后根据自己的理解,大致实现了一个简单版的。

他的大致流程如下:

  1. 只渲染可视区域的信息
  2. 有两个box,外面那个用来表示可视区,里面那个用来表示是所有的列表项
  3. 每当滚动条滚动的时候,去计算显示哪些
    这里有两种实现方式:
    1. 父元素是position: relative; 子元素absolute;来定位显示元素的位置,动态计算每个元素的位置
  4. 知道这个列表有多少条,也知道没一条的高度

确定一些元素的大小

  1. 每一条item的大小
  2. 可视区域的大小: 这样可以计算需要显示多少条
  3. 另一个父元素的大小,即列表的大小,需要计算滚动条滚动的距离,来计算应该从哪里开始展示
const wrapperStyle = {...STYLE_WRAPPER, height: height + "px"};
const innerHeight =  itemSize * itemCount,
    		innerStyle = {...STYLE_INNER, height: innerHeight + "px"};
return (
    <div ref={this.rootNode} style={wrapperStyle}>
    	<div style={innerStyle}>
    		{items}
    	</div>
    </div>
)

这是展示区域的样式,这里已经确定了每一个item的高度和可视区域的高度来实现的。

滚动计算展示的

这里只做了一个简单的例子,用来计算当滚动的时候,该显示的数据。

这里需要注意的是,当endIndex > lastIndex的时候,说明滚动条已经到底了,那么当endIndex 就该等于lastIndex。
而且在滚动的过程中,加了overscanCount,这是为了有所缓存,不至于滚动的时候,页面有所卡顿。

componentDidMount(){
	this.rootNode.current.addEventListener('scroll', this.handleScroll);
}
handleScroll = () => {
	const rootNode = this.rootNode.current,
		{showCount, overscanCount, lastIndex} = this,
		{itemSize} = this.props,
		scrollTop = rootNode.scrollTop,
		startIndex = parseInt(scrollTop/itemSize) + 1;
	let	endIndex = startIndex +  showCount + overscanCount;
	if(startIndex +  showCount > lastIndex){
		endIndex = lastIndex;
	}
	this.setState({
		startIndex: startIndex,
		endIndex: endIndex
	})
}

性能优化点

  1. 在滚动事件中增加了
handleScroll = () => {
	if(!this.ticking){
		requestAnimationFrame(this.caculateStartAndEndIndex);
		this.ticking = true;
	}

}
  1. 把每个节点的位置记录下来,这样就不需要每次都动态计算了
getStyle(index){
    const style = this.styleCache[index],
    	{itemSize} = this.props;
    
    if(style){
    	return style;
    }
    return this.styleCache[index] = {...STYLE_ITEM, top: index*itemSize + "px", left: 0, height: itemSize+"px"}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions