Vue Virtual Scroller 与 Element UI Table 集成方案
2024-12-27 13:54:41
Vue-virtual-scroller 与 Element UI Table 的集成
Element UI Table 组件基于配置式渲染表格行,它不像一些组件允许开发者直接控制每一行的渲染,这使得与 vue-virtual-scroller
集成遇到一些挑战。vue-virtual-scroller
旨在高效渲染大型列表,通过只渲染视口内的元素来提高性能。 本文分析此问题,并给出一些可能的解决方案。
问题分析
核心在于, el-table
使用内部逻辑来渲染行,并未暴露可以直接使用 vue-virtual-scroller
迭代的行容器。传统上, vue-virtual-scroller
需要你迭代一个数组,并用它包裹每一个渲染出来的项目(列表项或者表格行)。 但在Element UI 的Table中, el-table-column
组件的是列配置,而非行的构成。这种机制意味着你无法直接使用 v-virtual-scroller
包裹 el-table
的每一行。
解决方案
方案一: 使用 el-table
的插槽和虚拟滚动组件
此方案的核心在于,利用 el-table
的插槽自定义渲染每一行, 并引入虚拟滚动组件。你可以使用一个带有height
属性的div
来模拟 el-table
渲染的每一行,并且利用vue-virtual-scroller
渲染该div,达到虚拟滚动效果。
- 创建虚拟滚动包装器 : 构建一个通用组件来包裹
el-table
的行渲染。 这个组件内部使用vue-virtual-scroller
负责滚动。
<template>
<virtual-scroller
:items="tableData"
:item-size="rowHeight"
ref="scroller"
>
<template v-slot="{ item }">
<div :style="{height: rowHeight + 'px', lineHeight: rowHeight + 'px'}" class="custom-table-row">
<slot :item="item"></slot>
</div>
</template>
</virtual-scroller>
</template>
<script>
import { VirtualScroller } from 'vue-virtual-scroller'
export default{
name: "CustomTable",
props:{
tableData:{
type: Array,
required: true,
},
rowHeight:{
type: Number,
default: 40, // 设置行高度
}
},
components:{
VirtualScroller,
},
}
</script>
<style scoped>
.custom-table-row {
border-bottom: 1px solid #ebeef5;
}
</style>
- 使用包装器替换表格 : 修改
el-table
组件,使用上述包装器替换数据迭代渲染逻辑,并将表格行的渲染放到该组件的slot中。
<template>
<div>
<el-table style="width: 100%;" :header-cell-style="{background:'#eef0f3',color:'#606266'}">
<el-table-column
v-for="(item, index) in columns"
:key="index"
:prop="item.prop"
:label="item.label"
:width="item.width">
</el-table-column>
</el-table>
<CustomTable :table-data="tableData" :row-height="40">
<template v-slot="{item}">
<el-table style="width: 100%" :border="false" :show-header="false">
<el-table-column
v-for="(col,index) in columns"
:key="index"
:prop="col.prop"
>
<template v-slot>
<span> {{ item[col.prop] }}</span>
</template>
</el-table-column>
</el-table>
</template>
</CustomTable>
</div>
</template>
<script>
import CustomTable from './CustomTable.vue'; // 导入自定义包装器组件
export default {
components: { CustomTable},
data(){
return {
columns:[{
prop:'date',
label: 'Date',
width: 180,
},
{
prop:'name',
label:'Name',
width:180,
}],
tableData:[
{ date: '2016-05-03', name: 'Tom' },
{ date: '2016-05-02', name: 'Bob' },
{ date: '2016-05-04', name: 'Marry' },
{ date: '2016-05-01', name: 'Jack' },
{ date: '2016-05-05', name: 'Tom' },
{ date: '2016-05-06', name: 'Tom' },
{ date: '2016-05-07', name: 'Tom' },
{ date: '2016-05-08', name: 'Tom' },
{ date: '2016-05-09', name: 'Tom' },
{ date: '2016-05-10', name: 'Tom' },
{ date: '2016-05-11', name: 'Tom' },
{ date: '2016-05-12', name: 'Tom' },
{ date: '2016-05-13', name: 'Tom' },
{ date: '2016-05-14', name: 'Tom' },
{ date: '2016-05-15', name: 'Tom' }
]
}
},
}
</script>
这个方法核心是将行的渲染权交给自定义组件。它使用 vue-virtual-scroller
渲染一个占位的 div 模拟行的渲染。这带来了一些灵活性,但可能在样式控制上略显复杂。
方案二: 修改Element UI 的表格源码 (高阶)
另一种相对复杂的办法, 可以直接修改Element UI 的表格组件, 允许开发者使用 v-for
指令渲染行,这涉及到fork element UI项目修改其源代码,因此这个方案需要开发者对Element UI组件内部结构比较熟悉。
步骤简述 :
- Fork Element UI 代码仓库到本地。
- 定位
el-table
相关组件的源码。 - 修改表格渲染逻辑,使其可以接受外部传递的数据,然后配合
vue-virtual-scroller
组件。
这通常比较复杂且有侵入性,不推荐,因为这会让你的项目与你所使用的第三方库深度绑定。任何Element UI版本更新可能需要重新进行类似修改。
总结
将 vue-virtual-scroller
集成到 Element UI Table
中并非易事,因为两个组件的设计理念不同。方案一 通过创建中间组件作为桥梁,实现表格的虚拟滚动是一个较为可行的方案,尽管它增加了一层组件包装,在复杂度可以接受的范围内提高了表格性能,而 方案二 虽然是一种方式,但是不推荐。
无论你采用哪种方法, 都需要仔细考虑项目具体需求,评估方案可行性和潜在的维护成本。在着手修改之前,尽可能熟悉每一个组件,对可能造成影响的点做好测试。