VirtualList 虚拟滚动列表
如果项目中使用的是 0.x 版本的基础组件(@icedesign/base, @ali/ice, @alife/next),请在左侧导航顶部切换组件版本。
安装方法
- 在命令行中执行以下命令
npm install @alifd/next@latest -S
开发指南
何时使用
主要用于解决大数据情况下的渲染速度问题。组件的设计思想可以看这篇文章 https://zhuanlan.zhihu.com/p/55329238
API
VirtualList
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
children | 渲染的子节点 | any | - |
minSize | 最小加载数量 | Number | 1 |
pageSize | 一屏数量 | Number | 10 |
itemsRenderer | 父渲染函数,默认为 (items, ref) => {items}签名:Function() => void | Function | (items, ref) => <ul ref={ref}>{items}</ul> |
threshold | 缓冲区高度 | Number | 100 |
itemSizeGetter | 获取item高度的函数签名:Function() => void | Function | - |
jumpIndex | 设置跳转位置,需要设置 itemSizeGetter 才能生效, 不设置认为元素等高并取第一个元素高度作为默认高 | Number | 0 |
代码示例
使用 VirtualList 最简单的例子。
查看源码在线预览
import { VirtualList } from '@alifd/next';
const dataSource = [];
const generateLi = (index = 'index') => {
const data = [];
if (index % 3 === 0) {
return <li key={`key-${index}`} style={{lineHeight: '30px', background: '#5f83ff', color: '#fff'}}>key-{index}</li>;
} else {
return <li key={`key-${index}`} style={{lineHeight: '20px'}}>key-{index}</li>;
}
};
for (let i = 0; i < 1000; i++) {
dataSource.push(generateLi(i));
}
const demo = (
<div className={'virtual-box'}>
<VirtualList>
{dataSource}
</VirtualList>
</div>
);
ReactDOM.render(demo, mountNode);
.virtual-box {
height: 200px;
width: 200px;
border: 1px solid #ddd;
overflow: auto;
}
.virtual-box ul {
padding: 0;
margin: 0;
list-style: none;
}
.virtual-box li {
padding-left: 10px;
border-bottom: 1px solid #333;
}
使用 jumpIndex 设置初始位置
查看源码在线预览
import { VirtualList } from '@alifd/next';
const dataSource = [];
function generateLi(index) {
return (<li key={`key-${index}`} style={{lineHeight: '20px'}}>key-{index}</li>);
}
function generateData(len) {
for (let i = 0; i < len; i++) {
dataSource.push(generateLi(i));
}
}
class App extends React.Component {
state = {
initial: 50,
dataSource: generateData(1000)
}
onClick() {
this.setState({
initial: this.state.initial + 20
});
}
render() {
return (
<div>
<button onClick={this.onClick.bind(this)}>jump to {this.state.initial + 20}</button>
<br/>
<br/>
<div className={'virtual-box'}>
<VirtualList ref="virtual" jumpIndex={this.state.initial}>
{dataSource}
</VirtualList>
</div>
</div>
);
}
}
ReactDOM.render(<App />, mountNode);
.virtual-box {
height: 200px;
width: 200px;
border: 1px solid #ddd;
overflow: auto;
}
.virtual-box ul {
padding: 0;
margin: 0;
list-style: none;
}
.virtual-box li {
padding-left: 10px;
border-bottom: 1px solid #333;
}
使用 jumpIndex 设置初始位置, 并设置 itemSizeGetter
查看源码在线预览
import { VirtualList } from '@alifd/next';
const dataSource = [];
function generateLi(index) {
if (index % 3 === 0) {
return (<li key={`key-${index}`} style={{lineHeight: '30px', background: '#5f83ff', color: '#fff'}}>key-{index}</li>);
} else {
return (<li key={`key-${index}`} style={{lineHeight: '20px'}}>key-{index}</li>);
}
}
function generateData(len) {
for (let i = 0; i < len; i++) {
dataSource.push(generateLi(i));
}
}
class App extends React.Component {
state = {
initial: 20,
dataSource: generateData(1000)
}
componentDidMount() {
setTimeout(() => {
const instance = this.refs.virtual.getInstance();
instance.scrollTo(50);
}, 200);
}
getHeight(index) {
return index % 3 === 0 ? 30 : 20;
}
onClick() {
this.setState({
initial: this.state.initial + 20
});
}
render() {
return (
<div>
<button onClick={this.onClick.bind(this)}>jump to {this.state.initial + 20}</button>
<br/>
<br/>
<div className={'virtual-box'}>
<VirtualList ref="virtual" jumpIndex={this.state.initial} itemSizeGetter={this.getHeight.bind(this)}>
{dataSource}
</VirtualList>
</div>
</div>
);
}
}
ReactDOM.render(<App />, mountNode);
.virtual-box {
height: 200px;
width: 200px;
border: 1px solid #ddd;
overflow: auto;
}
.virtual-box ul {
padding: 0;
margin: 0;
list-style: none;
}
.virtual-box li {
padding-left: 10px;
border-bottom: 1px solid #333;
}