Virtualize虚拟列表
Virtual Scrolling虚拟滚动/Virtual List虚拟列表是前端一种列表加载技术,他模拟真实的容器滚动条,并支持在数据充足的情况下无限滚动和无限渲染,即便如此却很少消耗内存和性能,因为虚拟列表仅仅是渲染用户视线所及的部分,用户看不到的部分或者不关心的部分并不会被渲染。虚拟列表、懒加载和分页加载是三种长列表解决方案,各有优劣。
前言
虚拟滚动列表和真实滚动列表,使用相同的滚动条,但是他们渲染的内容是有差别的。真实滚动条的滚动距离与真实渲染直接相关,渲染的节点越多,可滚动的距离越长;而虚拟滚动的内容容器是由部分渲染节点,加上内容容器的translate偏移值伪造出了滚动条,虽然滚动距离很长,但是实际上渲染的节点很少,仅仅是铺满视线所及的区域。
因为虚拟滚动列表渲染的节点比较少,所以可以大大较少内存和性能消耗,提高加载速度;对于大型数据列表,在不分页前提下,使用虚拟滚动列表是比较科学的解决方案。
监听事件
事件监听也可以叫做执行钩子函数,当某事件被触发将执行用户自定义的钩子函数,在模块的创建到销毁的生命周期中,除了通用的ready、launch、init、reset、destroy、error等事件,本模块还支持以下专属事件。
- append:新增数据后执行,在模块参数中写作
onAppend
,该事件参数如下:- data:新数据,来自append方法中对新数据处理后的数据数据
- updateItem:更新某项数据后执行,在模块参数中写作
onUpdateItem
,该事件参数如下:- data:新数据,来自updateItem方法中对旧数据处理后的新数据
- rendered:完成渲染后执行,在模块参数中写作
onRendered
,该事件参数如下:- data:渲染完成后的数据,该数据为一个对象,属性如下:
- startIdx:本次渲染的起始索引
- endIdx:本次渲染的结束索引
- nodes:临时节点,为节点数组
- scrollVal:滚动条卷去的尺寸
- offsetVal:列表translate偏移值
- wrapSize:内容器的尺寸
- listSize:当前节点列表的尺寸
- data:渲染完成后的数据,该数据为一个对象,属性如下:
- getCont:获得数据之后执行,在模块参数中写作
onGetCont
,该事件参数如下:- data:刚获得的数据,数据为一个对象,包含content和source属性,content的值是一个数组将被添加到变量this.content中,source的值是原始数据
- exhausted:所有数据被渲染了之后执行,在模块参数中写作
onExhausted
,该事件参数如下:- data:即this.content变量,此时this.content中的每一项都被渲染了一遍
- toStart:滚动到头之后执行,在模块参数中写作
onToStart
,该事件无参数 - toEnd:滚动到尾之后执行,在模块参数中写作
onToEnd
,该事件无参数 - clear:清除后执行,在模块参数中写作
onClear
,该事件无参数
操作方法
除了通用的init、destroy、reset、update等方法,本模块还支持以下专属方法。
- append:新增数据,该方法参数如下:
- data:新数据,写法同
getContent
函数的第一个参数 - cb:回调函数,回调函数支持一个参数即新数据。
- data:新数据,写法同
- updateItem:更新某项数据,该方法参数如下:
- data:新数据,为一个对象,包含的属性如下:
- content:新值,新值可以是一个节点、一个字符串、一个数字或一个数据对象
- index:要更新的项目索引
- override:是否需要覆盖原数据,默认true即覆盖
- cb:回调函数,回调函数支持一个参数即新数据。
- data:新数据,为一个对象,包含的属性如下:
- scrollTo:跳转项目,该方法参数如下:
- index:跳转到指定项目的索引
- cb:回调函数,回调函数支持一个参数即跳转索引。
- toStart:跳转到头部,该方法无参数
- toEnd:跳转到尾部,该方法无参数
简单使用
我们使用Mockjs
模拟列表数据,将数据传入参数content
即可。
- 输出
- HTML
- JS
-
-
-
new ax.Virtualize('#virt02',{ content:Array(1000).fill(null).map((k,i)=>`${i}-${Mock.mock('@name')}`), });
水平滚动
默认为垂直方向的滚动,如果有必要可通过参数axis
设置水平滚动,即axis:'x'
。
- 输出
- HTML
- JS
-
-
-
new ax.Virtualize('#virt10',{ content:Array(1000).fill(null).map((k,i)=>`${i}-${Mock.mock('@name')}`), axis:'x', });
基本操作
本示例演示常用的操作方法。
- 输出
- HTML
- JS
-
-
-
let ins = new ax.Virtualize('#virt03',{ content:Array(1000).fill(null).map((k,i)=>`${i}-${Mock.mock('@name')}`), }); btn01.onclick = ()=>{ ins.append({content:Array(500).fill(null).map((k,i)=>`<i class="_c-error">${i}</i>`)}); } btn02.onclick = ()=>{ for(let k of ins.nodes){ ins.updateItem({ index:k.index, content:`<i class="_c-succ">${Mock.Random.cparagraph(1,8)}</i>` }); } } btn03.onclick = ()=>{ ins.clear(); } btn04.onclick = ()=>{ ins.scrollTo(~~(Math.random()*ins.content.length)); }
基础配置
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
axis | 'x'/'y' | 'y' | 滚动方向 |
size | number | 0 | 项目初始尺寸(px/rem) |
spill | number | 2 | 外溢缓冲项目数量 |
index | number | 0 | 起始渲染位置 |
dynamic | boolean | true | 项目尺寸是否可变 |
classes | string | '' | 追加样式类 |
节点名称配置
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
names.wrap | string | 'div' | 外容器节点名 |
names.list | string | 'div' | 列表节点名 |
names.cont | string | 'div' | 内部容器节点名 |
names.item | string | 'section' | 单项节点名 |
数据源配置
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
content | string | '' | 数据源内容 |
contType | 'text'/'html'/'node'/'image'/'async' | 'text' | 内容格式类型 |
contData | object | {} | 请求参数或媒体节点数据 |
ajax | object | {} | 异步请求配置 |
模板配置
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
tplStr | string | '' | 模板字符串 |
tplEng | string/null | null | 模板引擎类型 |
等待函数
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
b4Append | function | null | 添加节点前等待 |
b4UpdateItem | function | null | 更新项目前等待 |
b4Clear | function | null | 清空节点前等待 |
回调函数
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
onAppend | function | null | 添加节点后回调 |
onGetCont | function | null | 获取数据时回调 |
onExhausted | function | null | 所有数据渲染完回调 |
onToStart | function | null | 滚动到头部回调 |
onToEnd | function | null | 滚动到尾部回调 |
onUpdatedItem | function | null | 更新项目时回调 |
onRendered | function | null | 渲染完成回调 |
onError | function | null | 请求错误回调 |