虚拟滚动主要是在有限范围内渲染想要显示的数据,主要体现在懒加载数据和动态渲染上。如何提高虚拟滚动的操作性呢?请看本章解析
1.什么是虚拟滚动?代码如何实现?
VXE-Table提供了一种名为“虚拟滚动”的功能,该功能可以处理大量数据的渲染,避免了 DOM 元素过多导致的性能问题(最大可以支撑 5w 列、30w 行)。
在模板中使用 标签,并设置scroll-y(纵向)/scroll-x(横向)中的enabled属性为 true(ture为开启,false为关闭,默认为关闭)。
设置 height 属性以限制表格的高度。
设置 row-height 属性以指定每行的高度。
<vxe-table
border
height="200" //表格的高度
row-height="50" //行的高度
:scroll-y="{enabled: true}" //开启纵向虚拟滚动
:data="tableData">
<vxe-column type="seq" width="100"></vxe-column>
<vxe-column field="name" title="Name" sortable></vxe-column>
<vxe-column field="sex" title="Sex"></vxe-column>
<vxe-column field="age" title="Age"></vxe-column>
<vxe-column field="address" title="Address" show-overflow></vxe-column>
</vxe-table>
提示:
启用虚拟滚动后:show-overflow,show-header-overflow,show-footer-overflow 参数将根据不同场景各自触发生效,无法取消;如果需要支持,需将虚拟滚动关闭
性能优化:横向虚拟滚动由列宽决定性能,每一列的列宽越大就越流畅;纵向虚拟滚动由行高决定性能,每一行的高度越高就越流畅
2.滚动条定位
“虚拟滚动”的本质是动态渲染,所以如果想操作未渲染的自定义组件时,就需要将其跳转到响应的单元格位置,否则无法获取到未渲染数据行的id或者ref等各种信息,也就自然无法进行响应。所以滚动条定位就是单元格中自定义组件动态响应的前提。
首先需要为了访问vxe-table的DOM,需要定义一个ref
<vxe-table
border
ref="xTable" //设置指向vxe-table的引用
height="200" //表格的高度
row-height="50" //行的高度
:scroll-y="{enabled: true}" //开启纵向虚拟滚动
:data="tableData">
<vxe-column type="seq" width="100"></vxe-column>
<vxe-column field="name" title="Name" sortable></vxe-column>
<vxe-column field="sex" title="Sex"></vxe-column>
<vxe-column field="age" title="Age"></vxe-column>
<vxe-column field="address" title="Address" show-overflow></vxe-column>
</vxe-table>
然后在需要进行滚动条定位的地方加上如下代码
setTimeout(() => {
// x:是期望滚动到位置水平轴上距元素左上角的像素。
// y:是期望滚动到位置竖直轴上距元素左上角的像素。
// 回到滚动条顶端的代码就是 this.$refs.xTable.scrollTo(0, 0)
// 跳转到第20行的代码就是 this.$refs.xTable.scrollTo(0, 行高 * 20)
this.$refs.xTable.scrollTo(x, y)
}, 50)
提示:如果想要操作的数据行不在虚拟滚动队列(画面上显示的数据只是虚拟滚动队列里的一部分)里,是不会被渲染的。所以无法获取对应的DOM。
例如:画面上显示了1到5行,虚拟滚动队列里是1到8行。当你想要更改第20行时,需要先跳转到第20行,不然无法更改第二十行的样式等元素。
注:this.$refs.xTable.getTableData()可以查看目前的虚拟滚动队列
3.对单元格中的组件进行样式变更
如果想在单元格中对自定义的组件进行动态响应,例如焦点聚焦,更改样式等。就必须要在滚动条定位是动态响应的前提下进行。
首先在单元格中自定义一个input控件,并为其创建动态ref。
<vxe-table
border
ref="xTable" //设置指向vxe-table的引用
height="200" //表格的高度
row-height="50" //行的高度
:scroll-y="{enabled: true}" //开启纵向虚拟滚动
:edit-config="{trigger: 'click', mode: 'cell', showIcon: false}"//单击可编辑单元格
:data="tableData">
<vxe-column field="name" title="Name" width="260" >
<template #default="{ row, rowIndex }">
<div>
<input
:ref="'name'+rowIndex"//动态ref
tabindex="0"
v-model="row.name"
type="text"
maxlength="17"//最大入力17位
>
</div>
</template>
</vxe-column>
</vxe-table>
在想要实现动态响应的地方添加如下代码
setTimeout(() => {
this.$refs.xTable.scrollTo(0, 行高 * 响应行)//滚动条跳转到响应行
}, 50)
setTimeout(() => {
this.$refs['name' + 响应行].focus()//焦点落在相应行的input控件上
this.$refs['name' + 响应行].style.backgroundColor = '#fcd4d4'//input控件背景变红
}, 100)
//例如 行高20的表格,想要让第110行的name单元格动态响应,代码如下
setTimeout(() => {
this.$refs.xTable.scrollTo(0, 20* 110)
}, 50)
setTimeout(() => {
this.$refs['name' + 110].focus()
this.$refs['name' + 110].style.backgroundColor = '#fcd4d4'
}, 100)
4.虚拟样式缓存
与上述2和3不同的是,vxe-table中自带的方法可以不用担心虚拟滚动导致无法更改样式,vxe-table会在方法施行时对样式进行虚拟缓存,当渲染时默认渲染最新样式。拿单元格改色做例子。
引入更改单元格样式的方法
<vxe-table
border
ref="xTable" //设置指向vxe-table的引用
height="200" //表格的高度
row-height="50" //行的高度
:cell-style="tableCellStyle" // 调用单元格样式动态响应的方法
:scroll-y="{enabled: true}" //开启纵向虚拟滚动
:data="tableData">
<vxe-column type="seq" width="100"></vxe-column>
<vxe-column field="name" title="Name" sortable></vxe-column>
<vxe-column field="sex" title="Sex"></vxe-column>
<vxe-column field="age" title="Age"></vxe-column>
<vxe-column field="address" title="Address" show-overflow></vxe-column>
</vxe-table>
在tableCellStyle方法中实现动态样式
// rowIndex 当前行数
// column 列集合
tableCellStyle ({ rowIndex, column}) {
let rowStyle = {}
rowStyle.backgroundColor = '#fff !important'// 单元格背景默认为白色
if (column.field === 'name' && rowIndex === 20) { // 如果是第20行的name列单元格
rowStyle.backgroundColor = '#fcd4d4 !important'// 单元格背景为红色
}
return rowStyle
},