Virtualized Table 虚拟化表格
在前端开发领域,表格一直都是一个高频出现的组件,尤其是在中后台和数据分析场景。但是,对于 Table V1 来说,当一屏里超过 1000 条数据记录时,就会出现卡顿等性能问题,体验不是很好。
通过虚拟化表格组件,超大数据渲染将不再是一个头疼的问题。
TIP
该组件仍在测试中,生产环境使用可能有风险。若您发现了 bug 或问题,请于 GitHub 报告给我们以便修复。同时,有一些 API 并未在此文档中提及,因为部分还没有开发完全,因此我们不在此提及。
即使虚拟化的表格是高效的,但是当数据负载过大时,网络和内存容量也会成为您应用程序的瓶颈。因此请牢记,虚拟化表格永远不是最完美的解决方案,请考虑数据分页、过滤器等优化方案。
ts
import { createApp } from 'vue'
import { TableV2 as ElTableV2, AutoResizer as ElAutoResizer } from '@szhn/dh-design-pc'
const app = createApp()
app.use(ElTableV2)
app.use(ElAutoResizer)基础用法
让我们演示虚拟化表的性能,用 10 列和 1000 行渲染一个基本示例。
<template>
<el-auto-resizer style="height: 400px;">
<template #default="{ width, height }">
<el-table-v2
:columns="columns"
:data="data"
:width="width"
:height="height"
fixed
/>
</template>
</el-auto-resizer>
</template>
<script lang="ts" setup>
import { TableV2 as ElTableV2, AutoResizer as ElAutoResizer } from '@szhn/dh-design-pc'
const generateColumns = (length = 10, prefix = 'column-', props?: Record<string, unknown>) =>
Array.from({ length }).map((_, columnIndex) => ({
...props,
key: `${prefix}${columnIndex}`,
dataKey: `${prefix}${columnIndex}`,
title: `Column ${columnIndex}`,
width: 150,
}))
const generateData = (
columns: ReturnType<typeof generateColumns>,
length = 200,
prefix = 'row-',
) =>
Array.from({ length }).map((_, rowIndex) => {
return columns.reduce(
(rowData, column, columnIndex) => {
rowData[column.dataKey as string] = `Row ${rowIndex} - Col ${columnIndex}`
return rowData
},
{
id: `${prefix}${rowIndex}`,
parentId: null,
} as Record<string, unknown>,
)
})
const columns = generateColumns(10)
const data = generateData(columns, 1000)
</script>固定列
通过列配置中的 fixed: 'left' | 'right' 让列在横向滚动时保持固定。
<template>
<el-auto-resizer style="height: 320px;">
<template #default="{ width, height }">
<el-table-v2
:columns="columns"
:data="data"
:width="width"
:height="height"
fixed
/>
</template>
</el-auto-resizer>
</template>
<script lang="ts" setup>
import { TableV2 as ElTableV2, AutoResizer as ElAutoResizer } from '@szhn/dh-design-pc'
const columns = [
{ key: 'id', dataKey: 'id', title: 'ID', width: 80, fixed: true },
{ key: 'name', dataKey: 'name', title: '姓名', width: 150, fixed: true },
{ key: 'email', dataKey: 'email', title: '邮箱', width: 260 },
{ key: 'city', dataKey: 'city', title: '城市', width: 140 },
{ key: 'country', dataKey: 'country', title: '国家', width: 140 },
{ key: 'job', dataKey: 'job', title: '职位', width: 200 },
{ key: 'company', dataKey: 'company', title: '公司', width: 200 },
]
const data = Array.from({ length: 200 }, (_, i) => ({
id: i + 1,
name: `用户 ${i + 1}`,
email: `user${i + 1}@example.com`,
city: '海口',
country: '中国',
job: '前端工程师',
company: 'DHdesign Studio',
}))
</script>排序
通过列配置中的 sortable 以及表格的 sort-state 受控实现排序交互。
<template>
<el-auto-resizer style="height: 320px;">
<template #default="{ width, height }">
<el-table-v2
v-model:sort-state="sortState"
:columns="columns"
:data="sortedData"
:width="width"
:height="height"
@column-sort="onSort"
/>
</template>
</el-auto-resizer>
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue'
import { TableV2 as ElTableV2, AutoResizer as ElAutoResizer } from '@szhn/dh-design-pc'
const columns = [
{ key: 'id', dataKey: 'id', title: 'ID', width: 100, sortable: true },
{ key: 'name', dataKey: 'name', title: '姓名', width: 180 },
{ key: 'score', dataKey: 'score', title: '分数', width: 140, sortable: true },
]
const rawData = Array.from({ length: 120 }, (_, i) => ({
id: i + 1,
name: `用户 ${i + 1}`,
score: Math.floor(Math.random() * 100),
}))
const sortState = ref<{ key: string; order: 'asc' | 'desc' }>({ key: 'id', order: 'asc' })
const sortedData = computed(() => {
const { key, order } = sortState.value
return [...rawData].sort((a: any, b: any) =>
order === 'asc' ? a[key] - b[key] : b[key] - a[key],
)
})
const onSort = ({ key, order }: { key: string; order: 'asc' | 'desc' }) => {
sortState.value = { key, order }
}
</script>自定义单元格渲染器
当然,您可以根据您的需要呈现表格单元格。这是如何自定义您的单元格的简单例子。
<template>
<el-auto-resizer style="height: 320px;">
<template #default="{ width, height }">
<el-table-v2
:columns="columns"
:data="data"
:width="width"
:height="height"
/>
</template>
</el-auto-resizer>
</template>
<script lang="ts" setup>
import { h } from 'vue'
import { TableV2 as ElTableV2, AutoResizer as ElAutoResizer, Tag as ElTag } from '@szhn/dh-design-pc'
const columns = [
{ key: 'id', dataKey: 'id', title: 'ID', width: 80 },
{ key: 'name', dataKey: 'name', title: '姓名', width: 180 },
{
key: 'status',
dataKey: 'status',
title: '状态',
width: 160,
cellRenderer: ({ cellData }: { cellData: string }) =>
h(
ElTag,
{ type: cellData === '在线' ? 'success' : 'info', effect: 'plain' },
() => cellData,
),
},
]
const data = Array.from({ length: 80 }, (_, i) => ({
id: i + 1,
name: `成员 ${i + 1}`,
status: i % 2 === 0 ? '在线' : '离线',
}))
</script>API
TableV2 Attributes
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| columns | 列配置 | array | — |
| data | 表格数据 | array | — |
| width | 表格宽度 | number | — |
| height | 表格高度 | number | — |
| fixed | 是否有固定列 | boolean | false |
| row-height | 行高 | number | 50 |
| header-height | 表头高度 | number / number[] | 50 |
| estimated-row-height | 动态行高下的估算值 | number | — |
| sort-state | 受控排序状态 | object | — |
TableV2 Events
| 事件名 | 说明 |
|---|---|
| column-sort | 点击列头排序时触发 |
| row-click | 行点击时触发 |
| scroll | 滚动时触发 |
Column 配置(常用)
| 字段 | 说明 |
|---|---|
| key / dataKey | 列 key 与对应数据字段 |
| title | 表头标题 |
| width | 列宽 |
| fixed | 是否固定 |
| sortable | 是否可排序 |
| cellRenderer | 自定义单元格渲染函数 |
| headerCellRenderer | 自定义表头渲染函数 |
更多细节参见 Element Plus Virtualized Table 文档。
