Vxe UI vue vxe-table vxe-grid 本身就支持虚拟滚动以及灵活的扩展,可也是由于太过灵活,可定制化程度太高,比如单元格自定义渲染,一旦写得不好,就会影响渲染卡顿。
vxe-table 和 vxe-grid
直接使用 vxe-grid,grid 的渲染性能是最优的,全部功能比 table 强非常多。
全局参数
对于不同项目,只需要利用好全局参数,基本上就可以实现无需封装了,基本上所有组件都支持全局参数配置。
整理了最优的全局参数配置:
import{ VxeUI }from'vxe-table'
VxeUI.setConfig({
version:0,// 版本号,比如使用了相关的浏览器本地储存功能,当组件升级后系统自动重置数据,那么只需要不断增加版本即可
zIndex:2000,// 弹出层的层级,一般设置 2000 就够了
table:{
border:true,// 表格边框
showOverflow:true,// 单元格溢出隐藏,大幅提高渲染性能
autoResize:true,// 自动根据父容器适应调整宽高
columnConfig:{
resizable:true// 列宽拖动调整宽度},
editConfig:{
trigger:'click'// 默认点击编辑},
sortConfig:{
trigger:'cell'// 默认单元格编辑},
scrollX:{
enabled:false,// 默认关闭横向虚拟滚动,一般横向使用很少,局部开启就可以
gt:15},
scrollY:{
enabled:true,// 默认启用纵向虚拟滚动
gt:20}},// grid 会默认继承 table,所以无需重复设置一样的参数
grid:{
toolbarConfig:{
custom:true// 全局开启自定义列},// 数据代理相关配置,无使用就忽略
proxyConfig:{
showResponseMsg:false,
showActiveMsg:true,
response:{
total:'page.total',
result:'data',
list:'data'}}}})
使用
高度是非常重要的参数,可以固定,也可以设置 100% 自适应父容器,提高渲染性能
一千行渲染
一万行渲染
十万行渲染
<template><div><p><vxe-button@click="loadList(1000)">1k行</vxe-button><vxe-button@click="loadList(5000)">5k行</vxe-button><vxe-button@click="loadList(10000)">1w行</vxe-button><vxe-button@click="loadList(50000)">5w行</vxe-button><vxe-button@click="loadList(100000)">10w行</vxe-button></p><vxe-gridref="gridRef"v-bind="gridOptions"></vxe-grid></div></template><scriptsetup>import{ ref, reactive }from'vue'import{ VxeUI }from'vxe-table'const gridRef =ref()const gridOptions =reactive({
border:true,
showOverflow:true,
height:800,
loading:false,
scrollY:{
enabled:true,
gt:0},
columns:[{ type:'seq', title:'序号', width:100},{ field:'name', title:'Name', minWidth:180},{ field:'role', title:'Role', width:200},{ field:'num', title:'Num', width:200},{ field:'address', title:'Address', width:200}],
data:[]})// 模拟行数据constloadList=(size =200)=>{
gridOptions.loading =truesetTimeout(()=>{const dataList =[]for(let i =0; i < size; i++){
dataList.push({
id: i,
name:`名称${i} 名称名称 称`,
role:`role ${i}`,
num:20,
address:'shenzhen shen'})}const $grid = gridRef.value
if($grid){const startTime = Date.now()
$grid.loadData(dataList).then(()=>{
VxeUI.modal.message({
content:`加载时间 ${Date.now()- startTime} 毫秒`,
status:'success'})
gridOptions.loading =false})}},350)}loadList(500)</script>
可编辑
当列比较多时,就可以开启横向虚拟滚动,以下同时使用可编辑+纵向和横向虚拟滚动,极致流畅的渲染表格,同时还能支持任意扩展,单元格任意自定义(需要注意自定义的逻辑是否复杂,过度复杂会影响渲染性能)。
10000行 x 150列
滚动以及编辑输入都是丝滑流畅的
<template><div><p><vxe-button@click="loadDataAndColumns(100, 50)">100行50列</vxe-button><vxe-button@click="loadDataAndColumns(1000, 80)">1k行80列</vxe-button><vxe-button@click="loadDataAndColumns(5000, 100)">5k行100列</vxe-button><vxe-button@click="loadDataAndColumns(10000, 150)">1w行150列</vxe-button><vxe-button@click="loadDataAndColumns(30000, 200)">3w行200列</vxe-button></p><p><vxe-button@click="loadDataAndColumns(50, 50)">50行100列</vxe-button><vxe-button@click="loadDataAndColumns(80, 1000)">80行1k列</vxe-button><vxe-button@click="loadDataAndColumns(100, 5000)">100行5k列</vxe-button><vxe-button@click="loadDataAndColumns(150, 10000)">200行1w列</vxe-button><vxe-button@click="loadDataAndColumns(200, 30000)">200行3w列</vxe-button></p><vxe-gridref="gridRef"v-bind="gridOptions"></vxe-grid></div></template><scriptsetup>import{ ref, reactive, onMounted }from'vue'import{ VxeUI }from'vxe-table'const gridRef =ref()const gridOptions =reactive({
border:true,
loading:false,
showOverflow:true,
showHeaderOverflow:true,
showFooterOverflow:true,
height:800,
editConfig:{
trigger:'click',
mode:'cell'},
scrollY:{
enabled:true,
gt:0},
scrollX:{
enabled:true,
gt:0}})// 模拟行与列数据constloadDataAndColumns=(rowSize, colSize)=>{
gridOptions.loading =truesetTimeout(()=>{const $grid = gridRef.value
const colList =[]for(let i =0; i < colSize; i++){
colList.push({
field:`col${i}`,
title:`标题${i}`,
width:160,
editRender:{ name:'VxeInput'}})}const dataList =[]for(let i =0; i < rowSize; i++){const item ={
id:10000+ i
}for(let j =0; j < colList.length; j++){
item[`col${j}`]=`值_${i}_${j}`}
dataList.push(item)}if($grid){const startTime = Date.now()
$grid.loadColumn(colList).then(()=>{return $grid.loadData(dataList)}).then(()=>{
VxeUI.modal.message({
content:`加载时间 ${Date.now()- startTime} 毫秒`,
status:'success'})
gridOptions.loading =false})}},50)}onMounted(()=>{loadDataAndColumns(50,50)})</script>
更复杂的渲染
使用左右冻结列+复杂的单元格渲染、头像、上传图片、全屏预览,开关组件等
以下测试渲染1000-50000行速度
<template><div><vxe-button@click="loadData(5000)">加载5k条</vxe-button><vxe-button@click="loadData(10000)">加载1w条</vxe-button><vxe-button@click="loadData(50000)">加载5w条</vxe-button><vxe-gridv-bind="gridOptions"></vxe-grid></div></template><scriptsetup>import{ reactive, nextTick }from'vue'import{ VxeUI }from'vxe-table'const flag1CellRender =reactive({
name:'VxeSwitch'})const imgUrlCellRender =reactive({
name:'VxeImage',
props:{
width:36,
height:36}})const imgList1CellRender =reactive({
name:'VxeUpload',
props:{
mode:'image',
readonly:true,
moreConfig:{
maxCount:2},
imageStyle:{
width:40,
height:40}}})const gridOptions =reactive({
border:true,
showOverflow:true,
showHeaderOverflow:true,
showFooterOverflow:true,
loading:false,
height:800,
columnConfig:{
resizable:true},
scrollX:{
enabled:true,
gt:0},
scrollY:{
enabled:true,
gt:0},
columns:[{ title:'列0', field:'col0', width:100, fixed:'left'},{ title:'列1', field:'imgUrl', width:80, fixed:'left', cellRender: imgUrlCellRender },{ title:'列2', field:'col2', width:90, fixed:'left'},{ title:'列3', field:'col3', width:200},{ title:'列4', field:'col4', width:140},{ title:'列5', field:'col5', width:300},{ title:'列6', field:'col6', width:160},{ title:'列7', field:'col7', width:120},{ title:'列8', field:'col8', width:400},{ title:'列9', field:'col9', width:160},{ title:'列10', field:'col10', width:160},{ title:'列11', field:'col11', width:180},{ title:'列12', field:'col12', width:160},{ title:'列13', field:'col13', width:80},{ title:'列14', field:'col14', width:120},{ title:'列15', field:'col15', width:360},{ title:'列16', field:'col16', width:150},{ title:'列17', field:'col17', width:380},{ title:'列18', field:'col18', width:100},{ title:'列19', field:'col19', width:290},{ title:'列20', field:'col20', width:80},{ title:'列21', field:'col21', width:100},{ title:'列22', field:'col22', width:120},{ title:'列23', field:'col23', width:270},{ title:'列24', field:'col24', width:330},{ title:'列25', field:'col25', width:460},{ title:'列26', field:'col26', width:280},{ title:'列27', field:'col27', width:220},{ title:'列28', field:'col28', width:120},{ title:'列29', field:'col29', width:180},{ title:'列30', field:'col30', width:500},{ title:'列31', field:'col31', width:600},{ title:'列32', field:'col32', width:100},{ title:'列33', field:'col33', width:490},{ title:'列34', field:'col34', width:100},{ title:'列35', field:'col35', width:150},{ title:'列36', field:'col36', width:800},{ title:'列37', field:'col37', width:400},{ title:'列38', field:'col38', width:800},{ title:'列39', field:'col39', width:360},{ title:'列40', field:'col40', width:420},{ title:'列41', field:'col41', width:100},{ title:'列42', field:'col42', width:120},{ title:'列43', field:'col43', width:280},{ title:'列44', field:'col44', width:170},{ title:'列45', field:'col45', width:370},{ title:'列46', field:'col46', width:420},{ title:'列47', field:'col47', width:170},{ title:'列48', field:'col48', width:400},{ title:'列49', field:'col49', width:220},{ title:'列50', field:'col50', width:170},{ title:'列51', field:'col51', width:160},{ title:'列52', field:'col52', width:500},{ title:'列53', field:'col53', width:280},{ title:'列54', field:'col54', width:170},{ title:'列55', field:'col55', width:370},{ title:'列56', field:'col56', width:120},{ title:'列57', field:'col57', width:170},{ title:'列58', field:'col58', width:400},{ title:'列59', field:'col59', width:220},{ title:'列60', field:'col60', width:650},{ title:'列61', field:'col61', width:600},{ title:'列62', field:'col62', width:100},{ title:'列63', field:'col63', width:490},{ title:'列64', field:'col64', width:100},{ title:'列65', field:'col65', width:150},{ title:'列66', field:'col66', width:800},{ title:'列67', field:'col67', width:400},{ title:'列68', field:'col68', width:800},{ title:'列69', field:'col69', width:360},{ title:'列70', field:'col70', width:650},{ title:'列71', field:'col71', width:600},{ title:'列72', field:'col72', width:100},{ title:'列73', field:'col73', width:490},{ title:'列74', field:'col74', width:100},{ title:'列75', field:'col75', width:150},{ title:'列76', field:'col76', width:800},{ title:'列77', field:'col77', width:400},{ title:'列78', field:'col78', width:800},{ title:'列79', field:'col79', width:360},{ title:'列80', field:'col80', width:650},{ title:'列81', field:'col81', width:600},{ title:'列82', field:'col82', width:100},{ title:'列83', field:'col83', width:490},{ title:'列84', field:'col84', width:100},{ title:'列85', field:'col85', width:150},{ title:'列86', field:'col86', width:800},{ title:'列87', field:'col87', width:400},{ title:'列88', field:'col88', width:800},{ title:'列89', field:'col89', width:360},{ title:'列90', field:'col90', width:650},{ title:'列91', field:'col91', width:600},{ title:'列92', field:'col92', width:100},{ title:'列93', field:'col93', width:490},{ title:'列94', field:'col94', width:100},{ title:'列95', field:'col95', width:150},{ title:'列96', field:'col96', width:800},{ title:'列97', field:'col97', width:400},{ title:'列98', field:'col98', width:70, fixed:'right'},{ title:'列99', field:'imgList1', width:120, fixed:'right', cellRender: imgList1CellRender },{ title:'列100', field:'flag1', width:100, fixed:'right', cellRender: flag1CellRender }],
data:[]})// 模拟行数据constloadData=(rowSize)=>{const dataList =[]for(let i =0; i < rowSize; i++){const item ={
id:10000+ i,
imgUrl: i %3===0?'https://vxeui.com/resource/img/546.gif':'https://vxeui.com/resource/img/673.gif',
imgList1: i %4===0?[{ name:'fj577.jpg', url:'https://vxeui.com/resource/img/fj577.jpg'}]:[{ name:'fj573.jpeg', url:'https://vxeui.com/resource/img/fj573.jpeg'},{ name:'fj562.png', url:'https://vxeui.com/resource/img/fj562.png'}],
flag1: i %5===0}for(let j =0; j <120; j++){
item[`col${j}`]=`值_${i}_${j}`}
dataList.push(item)}
gridOptions.loading =truesetTimeout(()=>{const startTime = Date.now()
gridOptions.data = dataList
gridOptions.loading =falsenextTick(()=>{
VxeUI.modal.message({
content:`加载时间 ${Date.now()- startTime} 毫秒`,
status:'success'})})},100)}loadData(200)</script>
以上复杂度还不是很高,当渲染复杂度更大是,鼠标滚轮的速度快于渲染速度,这是就会出现渲染期空白。
可以通过设置参数 scroll-y.mode = ‘wheel’ 解决,虚拟滚动操作过快渲染期空白问题
// ...
scrollY:{
enabled:true,
gt:0,
mode:'wheel'},// ...
滚动操作是非常流畅的。
版权归原作者 大猩猩X 所有, 如有侵权,请联系我们删除。