vxe-table的表格功能强,性能高,支持虚拟滚动和懒加载。我在工作中用到i-view的表格和hui的表格,在数据量大,尤其是树状而且数据量大时,加载展示很缓慢。这里准备将需要大屏展示的表格替换成vxe-grid(vxe-grid是vxe-table的高级版本,支持动态自定义列)来使用。
gitee地址: https://gitee.com/xuliangzhan_admin/vxe-table
文档地址:https://xuliangzhan_admin.gitee.io/vxe-table/#/table/api
测试的性能文件记录如下:
1. 新建html文件,引入vue和vxe-table的相关cdn文件:
<!-- 引入vue -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 引入样式 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vxe-table/lib/style.css">
<!-- 引入脚本 -->
<script src="https://cdn.jsdelivr.net/npm/xe-utils"></script>
<script src="https://cdn.jsdelivr.net/npm/vxe-table"></script>
2. 新建treeTable.js文件,封装vxe-grid组件,将是否懒加载、节点数、子节点数封装成对外接口。
props: {
// 是否懒加载
ifLazy: {
type: Boolean,
default: false
},
// 节点数(最外层)
nodeCount: {
type: Number,
default: 1000
},
// 最外层节点上的每个节点的子节点数
childrenCount: {
type: Number,
default: 10
}
}
表格数据在proxy-config属性中获取。懒加载时,需要配置的属性如下:
children | 树子节点的属性
|
lazy | 是否使用懒加载(需要配合 hasChild )
|
hasChild | 只对 lazy 启用后有效,标识是否存在子节点,从而控制是否允许被点击
|
loadMethod | 该方法用于异步加载子节点(必须返回 Promise<any[]> 对象) |
3. 在父节点中使用treeTable.js中定义的子组件,且挂载在dom中。
完成的效果图:
完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>查看表格效率</title>
<!-- 引入vue -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 引入样式 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vxe-table/lib/style.css">
<!-- 引入脚本 -->
<script src="https://cdn.jsdelivr.net/npm/xe-utils"></script>
<script src="https://cdn.jsdelivr.net/npm/vxe-table"></script>
</head>
<body>
<div>
<div id="tablContent"></div>
</div>
<script src="./treeTable.js"></script>
<script>
let vueParent = new Vue({
el: '#tablContent',
template: `
<div>
<p>{{ifLazy?"懒加载":"完全加载"}}耗时({{nodeCount}}*{{childrenCount}}子节点):{{costTime}}毫秒</p>
<vxeTable :ifLazy="ifLazy" :nodeCount="nodeCount" :childrenCount="childrenCount" @onUpdateCost="getCost"></vxeTable>
</div>
`,
components: {
'vxeTable': vxeTable
},
data() {
return {
ifLazy: true,
nodeCount: 100,
childrenCount: 100,
costTime: 0
}
},
methods: {
getCost(value){
this.costTime = value
}
}
})
</script>
</body>
</html>
treeTable.js:
let vxeTable = {
template: `
<vxe-grid
border
resizable
height="400"
:proxy-config="tableProxy"
:columns="tableColumn"
:tree-config="treeConfig"></vxe-grid>
`,
props: {
ifVirtualScroll: {
type: Boolean,
default: false
},
// 是否懒加载
ifLazy: {
type: Boolean,
default: false
},
// 节点数(最外层)
nodeCount: {
type: Number,
default: 1000
},
// 最外层节点上的每个节点的子节点数
childrenCount: {
type: Number,
default: 10
}
},
data () {
return {
// 用于记录加载前的时间
beginTime: undefined,
// 数据代理
tableProxy: {
ajax: {
// 查询根节点
query: () => {
return this.getDatas(this.nodeCount, this.ifLazy?0:this.childrenCount, true)
}
}
},
// 自定义列格式
tableColumn: [
{ field: 'id', title: 'ID', width: 200, treeNode: true },
{ field: 'name', title: '名称', width: 100},
{ field: 'size', title: '大小', width: 100 },
{ field: 'createTime', title: '创建时间'},
{ field: 'updateTime', title: '修改时间'}
]
}
},
computed: {
// 配置
treeConfig(){
return this.ifLazy ?
{
lazy: true,
children: 'children',
hasChild: 'hasChild',
loadMethod: this.loadChildrenMethod
}:
{}
}
},
methods: {
// 生成数据,以promise格式返回
getDatas(dataCount, childrenCount=0, hasChild= false) {
return new Promise((resolve, reject) => {
setTimeout(() => {
let _data = []
for(let i=0; i<dataCount; i++) {
let _item =
{
id: i,
name: '名称',
size: 100,
createTime: new Date(),
updateTime: new Date(),
children: []
}
if(!this.ifLazy && childrenCount) {
for(let j=0; j<childrenCount; j++){
_item.children.push(
{
id: i * 10000 +j,
name: '子节点名称',
size: 200,
createTime: new Date(),
updateTime: new Date(),
}
)
}
} else if(hasChild){
_item.hasChild = true
}
_data.push(_item)
}
// 记录初始时间
this.beginTime = (new Date()).valueOf();
// 把数据交给表格
resolve(_data);
// 记录加载完成时间
setTimeout(() => {
let _endTime = (new Date()).valueOf();
this.$emit('onUpdateCost', _endTime-this.beginTime);
}, 0);
}, 0);
})
},
// 异步加载子节点
loadChildrenMethod ({ row }) {
return this.getDatas(this.childrenCount, 0)
}
}
}
在我的机器上测试结果:
(ps: 看了下dom,vxe-grid在我设置了height的情况下,并没有自动的给我虚拟滚动呀 😮,原来树状不能与虚拟滚动并存/(ㄒoㄒ)/~~)