一个真正的实现了 DOM 节点回收和复用的高性能虚拟长列表组件
npm install --save react-typed-recyclelist
# or
yarn add react-typed-recyclelist
import List, { StoreComponent, useStoreState } from 'react-typed-recyclelist';
git clone https://github.com/weird94/react-typed-recyclelist.git
cd react-typed-recyclelist
yarn
yarn dev-demo
属性 | 类型 | 默认 | 必填 | 描述 |
---|---|---|---|---|
Header | ComponentType<HeaderProps> |
null | 列表 header 组件 | |
Footer | ComponentType<FooterProps> |
null | 列表 footer 组件 | |
cellData | CellData<T>[] |
true |
列表渲染的数据(参考 demo) | |
height | number |
true |
列表容器的高度 | |
width | number |
true |
列表容器的宽度 | |
style | React.CSSProperties |
列表样式 | ||
className | string |
列表 class | ||
renderAccuary | number |
5 | 列表真实渲染因子真实渲染内容高度 = renderAccuary * 列表容器高度 |
|
scrollComputeThrottle | number |
100 | 列表触发渲染重新计算的滚动距离 (这个参数可以结合 renderAccuary 以及 item 的高度进行性能调优) | |
defaultScrollTop | number |
0 | 列表初始滚动的位置 | |
onScroll | (scrollTop: number, event) => void; |
滚动时触发的事件,返回当前滚动的距离 (频发触发,业务侧最好做好节流) | ||
onEndReached | () => void |
滚动区域还剩 onEndReachedThreshold 的长度时触发 |
||
onEndReachedThreshold | number |
设置加载更多的偏移 | ||
onCellShow | (index: number) => void |
cell 曝光事件,返回 cell 处于列表中的 index | ||
onCellHide | (index: number) => void |
cell 消失事件,返回 cell 处于列表中的 index | ||
onHeaderShow | () => void |
header 曝光事件 | ||
onHeaderHide | () => void |
header 消失事件 | ||
onFooterShow | () => void |
footer 曝光事件 | ||
onFooterHide | () => void |
footer 消失事件 |
scrollTo(scrollTop: number): void
: 指定列表滚动到特定位置
useStoreState
import { useStoreState } from 'react-typed-recyclelist';
const Cell = memo((props: CellProps<{ name: string }>) => {
const [active, setActive] = useStoreState(false, 'active', props);
};
// useStoreState 是为了让 cell 组件能够实现自状态而设计
// 通过将状态寄存在 list 内部的 stateMap 上而实现
StoreComponent
import { StoreComponent } from 'react-typed-recyclelist';
class CellComponent extends StoreComponent {
state = {
a: 1,
b: 2,
};
render() {
return <div>{this.state.a}</div>;
}
// 如果你需要使用这个生命周期,你必须调用 super.componentDidUpdate();
componentDidUpdate() {
super.componentDidUpdate();
// ...
}
// 如果你需要使用这个生命周期,你必须调用 super.componentDidMount();
componentDidMount() {
super.componentDidMount();
// ...
}
}
const Cell = memo((props: CellProps<{ name: string }>) => {
const { style, index } = props;
return (
<div
style={{
...style,
backgroundColor: index % 2 === 0 ? 'white' : 'yellow',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<span>{props.data.name + props.index}</span>
</div>
);
});
并且, 我们会保证 props 中每个属性的前后一致性, 所以你可以放心的使用 React.memo
或者 React.PureComponent
我们开放了一些参数用于你在实际使用中自己进行部分的调优
- renderAccuary: 列表真实渲染因子
真实渲染内容高度 = renderAccuary * 列表容器高度
默认为 5 - scrollComputeThrottle: 列表触发重新计算真实渲染内容所需要滚动的距离,这个参数决定了列表在滚动过程中的计算量的大小。默认为 100
所以,如果你出现了上述情况,不妨试试将这两个参数调大一些。
我们为每个 cell 实现了状态寄存,可以参考
如果顺序会发生改变的情况下,
- 我们提供了 sortKey props 来标示列表顺序的版本,以此驱动列表重新渲染并且清空回收池
- 我们允许你为数据打上唯一的 uniqueKey,这样来保证 store 和数据的一一对应