Appearance
table
Table 表格
Table 组件用于展示结构化数据,默认支持分页。当 total > 0
时会自动显示分页;也可以通过传入 showPagination
强制显示分页。
在线演示
下方为真实渲染的 Table 组件示例(非代码块),包含分页与基础列展示。
ID | 名称 | 年龄 | 地址 |
---|
1 | 用户1 | 18 | 城市-1 |
2 | 用户2 | 19 | 城市-2 |
3 | 用户3 | 20 | 城市-3 |
4 | 用户4 | 21 | 城市-4 |
5 | 用户5 | 22 | 城市-5 |
6 | 用户6 | 23 | 城市-1 |
7 | 用户7 | 24 | 城市-2 |
8 | 用户8 | 25 | 城市-3 |
9 | 用户9 | 26 | 城市-4 |
10 | 用户10 | 27 | 城市-5 |
共 36 条
更多在线示例(每种用法一个预览)
基础用法示例:
ID 名称 年龄 地址 1 用户1 18 城市-1 2 用户2 19 城市-2 3 用户3 20 城市-3 4 用户4 21 城市-4 5 用户5 22 城市-5 6 用户6 23 城市-1 7 用户7 24 城市-2 8 用户8 25 城市-3 9 用户9 26 城市-4 10 用户10 27 城市-5 总条数显式开启分页(
total=0
时仍显示):ID 名称 年龄 地址 1 用户1 18 城市-1 2 用户2 19 城市-2 3 用户3 20 城市-3 4 用户4 21 城市-4 5 用户5 22 城市-5 6 用户6 23 城市-1 7 用户7 24 城市-2 8 用户8 25 城市-3 9 用户9 26 城市-4 10 用户10 27 城市-5 总条数自定义分页文案与页大小:
ID 名称 年龄 地址 1 用户1 18 城市-1 2 用户2 19 城市-2 3 用户3 20 城市-3 4 用户4 21 城市-4 5 用户5 22 城市-5 6 用户6 23 城市-1 7 用户7 24 城市-2 8 用户8 25 城市-3 9 用户9 26 城市-4 10 用户10 27 城市-5 共 35 条空数据与占位文案:
ID 名称 年龄 地址 暂无数据 自定义列宽与对齐:
ID 名称 分数 1 用户1 87 2 用户2 63 3 用户3 78 4 用户4 88 5 用户5 73 6 用户6 84 7 用户7 75 8 用户8 89 总条数使用
rowKey
:唯一键 名称 row-1761037328954-0 记录-1 row-1761037328954-1 记录-2 row-1761037328954-2 记录-3 row-1761037328954-3 记录-4 row-1761037328954-4 记录-5 总条数不同尺寸:
ID 名称 1 用户1 2 用户2 3 用户3 4 用户4 5 用户5 6 用户6 总条数ID 名称 1 用户1 2 用户2 3 用户3 4 用户4 5 用户5 6 用户6 总条数ID 名称 1 用户1 2 用户2 3 用户3 4 用户4 5 用户5 6 用户6 总条数列宽拖拽:
ID 名称 年龄 地址 ID 名称 年龄 地址 1 用户1 18 城市-1 1 用户1 18 城市-1 2 用户2 19 城市-2 2 用户2 19 城市-2 3 用户3 20 城市-3 3 用户3 20 城市-3 4 用户4 21 城市-4 4 用户4 21 城市-4 5 用户5 22 城市-5 5 用户5 22 城市-5 6 用户6 23 城市-1 6 用户6 23 城市-1 7 用户7 24 城市-2 7 用户7 24 城市-2 8 用户8 25 城市-3 8 用户8 25 城市-3 9 用户9 26 城市-4 9 用户9 26 城市-4 10 用户10 27 城市-5 10 用户10 27 城市-5 总条数提示:将鼠标移动到表头最右侧,即可拖拽调整列宽。
自定义单元格插槽(操作列):
ID 名称 年龄 操作 1 用户1 18 2 用户2 19 3 用户3 20 4 用户4 21 5 用户5 22 6 用户6 23 7 用户7 24 8 用户8 25 9 用户9 26 10 用户10 27 总条数使用子组件定义列(Element Plus 风格):
总条数事件用法示例(监听
pageChange
):ID 名称 年龄 地址 1 用户1 18 城市-1 2 用户2 19 城市-2 3 用户3 20 城市-3 4 用户4 21 城市-4 5 用户5 22 城市-5 6 用户6 23 城市-1 7 用户7 24 城市-2 8 用户8 25 城市-3 9 用户9 26 城市-4 10 用户10 27 城市-5 总条数服务端分页(模拟请求):
ID 名称 年龄 地址 暂无数据 总条数动态列显示/隐藏:
ID 名称 年龄 地址 ID 名称 年龄 地址 1 用户1 18 城市-1 1 用户1 18 城市-1 2 用户2 19 城市-2 2 用户2 19 城市-2 3 用户3 20 城市-3 3 用户3 20 城市-3 4 用户4 21 城市-4 4 用户4 21 城市-4 5 用户5 22 城市-5 5 用户5 22 城市-5 6 用户6 23 城市-1 6 用户6 23 城市-1 7 用户7 24 城市-2 7 用户7 24 城市-2 8 用户8 25 城市-3 8 用户8 25 城市-3 9 用户9 26 城市-4 9 用户9 26 城市-4 10 用户10 27 城市-5 10 用户10 27 城市-5 总条数列顺序拖动(外部状态):
ID名称年龄地址ID名称年龄地址ID 名称 年龄 地址 ID 名称 年龄 地址 1 用户1 18 城市-1 1 用户1 18 城市-1 2 用户2 19 城市-2 2 用户2 19 城市-2 3 用户3 20 城市-3 3 用户3 20 城市-3 4 用户4 21 城市-4 4 用户4 21 城市-4 5 用户5 22 城市-5 5 用户5 22 城市-5 6 用户6 23 城市-1 6 用户6 23 城市-1 7 用户7 24 城市-2 7 用户7 24 城市-2 8 用户8 25 城市-3 8 用户8 25 城市-3 总条数固定表头与横向滚动:
ID 名称 部门 角色 邮箱 地址 1 用户1 部门-1 角色-1 user1@example.com 城市-1 2 用户2 部门-2 角色-2 user2@example.com 城市-2 3 用户3 部门-3 角色-3 user3@example.com 城市-3 4 用户4 部门-4 角色-1 user4@example.com 城市-4 5 用户5 部门-1 角色-2 user5@example.com 城市-5 6 用户6 部门-2 角色-3 user6@example.com 城市-1 7 用户7 部门-3 角色-1 user7@example.com 城市-2 8 用户8 部门-4 角色-2 user8@example.com 城市-3 9 用户9 部门-1 角色-3 user9@example.com 城市-4 10 用户10 部门-2 角色-1 user10@example.com 城市-5 总条数横向滚动(内置属性
scrollX
):ID 名称 部门 角色 邮箱 地址 城市 国家 邮编 1 用户1 部门-1 角色-1 user1@example.com 城市-1 城市-1 国家-1 100000 2 用户2 部门-2 角色-2 user2@example.com 城市-2 城市-2 国家-2 100001 3 用户3 部门-3 角色-3 user3@example.com 城市-3 城市-3 国家-3 100002 4 用户4 部门-4 角色-1 user4@example.com 城市-4 城市-4 国家-4 100003 5 用户5 部门-1 角色-2 user5@example.com 城市-5 城市-5 国家-5 100004 6 用户6 部门-2 角色-3 user6@example.com 城市-1 城市-6 国家-6 100005 7 用户7 部门-3 角色-1 user7@example.com 城市-2 城市-7 国家-7 100006 8 用户8 部门-4 角色-2 user8@example.com 城市-3 城市-8 国家-1 100007 9 用户9 部门-1 角色-3 user9@example.com 城市-4 城市-9 国家-2 100008 10 用户10 部门-2 角色-1 user10@example.com 城市-5 城市-10 国家-3 100009 总条数
基础用法
vue
<script setup lang="ts">
import { ref } from "vue";
const columns = [
{ key: "id", title: "ID", width: 80 },
{ key: "name", title: "名称" },
{ key: "age", title: "年龄", align: "center", width: 100 },
{ key: "address", title: "地址" },
];
const data = Array.from({ length: 35 }).map((_, i) => ({
id: i + 1,
name: `用户${i + 1}`,
age: 18 + (i % 10),
address: `城市-${(i % 5) + 1}`,
}));
const currentPage = ref(1);
const pageSize = ref(10);
</script>
<template>
<c-table
:columns="columns"
:data="data"
:total="data.length"
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
/>
</template>
显式开启分页
当 total
为 0 时,仍可通过 showPagination
强制显示分页。
vue
<c-table
:columns="columns"
:data="data"
:total="0"
:show-pagination="true"
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
/>
自定义分页文案与页大小
vue
<c-table
:columns="columns"
:data="data"
:total="data.length"
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:page-sizes="[5, 10, 20, 50]"
:show-size-changer="true"
:show-total="true"
total-text="共 {total} 条"
/>
空数据与占位文案
vue
<c-table :columns="columns" :data="[]" :total="0" empty-text="暂无数据" />
自定义列宽与对齐
通过在 columns
中设置 width
与 align
可控制列的宽度与文字对齐方式。
vue
<script setup lang="ts">
const alignColumns = [
{ key: "id", title: "ID", width: 80, align: "center" },
{ key: "name", title: "名称", width: 160 },
{ key: "score", title: "分数", align: "right", width: 100 },
];
const alignData = Array.from({ length: 8 }).map((_, i) => ({
id: i + 1,
name: `用户${i + 1}`,
score: Math.round(60 + Math.random() * 40),
}));
</script>
<template>
<c-table
:columns="alignColumns"
:data="alignData"
:total="alignData.length"
/>
<!-- 可强制显示分页(示例:total 为 0 但仍显示) -->
<c-table
:columns="alignColumns"
:data="alignData"
:total="0"
:show-pagination="true"
/>
<!-- 仅设置列宽,不设置分页 -->
<c-table :columns="alignColumns" :data="alignData" :total="0" />
</template>
使用 rowKey
当数据项不使用默认的 id
字段作为唯一标识时,可通过 rowKey
指定唯一键字段,提升列表渲染稳定性。
vue
<script setup lang="ts">
const uuidColumns = [
{ key: "uuid", title: "唯一键", width: 220 },
{ key: "name", title: "名称" },
];
const uuidData = Array.from({ length: 5 }).map((_, i) => ({
uuid: `row-${Date.now()}-${i}`,
name: `记录-${i + 1}`,
}));
</script>
<template>
<c-table
:columns="uuidColumns"
:data="uuidData"
:total="uuidData.length"
row-key="uuid"
/>
</template>
不同尺寸
通过 size
控制表格的整体视觉密度,提供 small | medium | large
三种尺寸。
vue
<script setup lang="ts">
const sizeColumns = [
{ key: "id", title: "ID", width: 80 },
{ key: "name", title: "名称" },
];
const sizeData = Array.from({ length: 6 }).map((_, i) => ({
id: i + 1,
name: `用户${i + 1}`,
}));
</script>
<template>
<div class="table-size-demo">
<c-table
size="small"
:columns="sizeColumns"
:data="sizeData"
:total="sizeData.length"
/>
<c-table
size="medium"
:columns="sizeColumns"
:data="sizeData"
:total="sizeData.length"
/>
<c-table
size="large"
:columns="sizeColumns"
:data="sizeData"
:total="sizeData.length"
/>
</div>
</template>
<style>
.table-size-demo .c-table + .c-table {
margin-top: 16px;
}
</style>
### 列宽拖拽(可选) 通过为组件传入 `columnResizable` 开启列宽拖拽,支持通过
`minColumnWidth` 与 `maxColumnWidth`
限制拖拽范围(单位:px)。当前版本仅支持像素宽度的列拖拽(不支持百分比宽度)。
```vue
<script setup lang="ts">
const dragColumns = [
{ key: "id", title: "ID", align: "center" },
{ key: "name", title: "名称" },
{ key: "age", title: "年龄", align: "center" },
{ key: "address", title: "地址" },
{ key: "id", title: "ID", align: "center" },
{ key: "name", title: "名称" },
{ key: "age", title: "年龄", align: "center" },
{ key: "address", title: "地址" },
{ key: "id", title: "ID", align: "center" },
{ key: "name", title: "名称" },
{ key: "age", title: "年龄", align: "center" },
{ key: "address", title: "地址" },
];
const dragData = Array.from({ length: 12 }).map((_, i) => ({
id: i + 1,
name: `用户${i + 1}`,
age: 18 + (i % 10),
address: `城市-${(i % 5) + 1}`,
}));
</script>
<template>
<c-table
:columns="dragColumns"
:data="dragData"
:total="dragData.length"
column-resizable
:min-column-width="80"
:max-column-width="500"
/>
<p class="tip">提示:将鼠标移动到表头最右侧,即可拖拽调整列宽。</p>
</template>
### 自定义单元格插槽(操作列)
每列会自动以其 `key` 作为插槽名称。可通过具名插槽自定义单元格内容,例如添加操作按钮或富文本内容。
```vue
<script setup lang="ts">
import { ref } from 'vue'
const actionColumns = [
{ key: 'id', title: 'ID', width: 80, align: 'center' },
{ key: 'name', title: '名称' },
{ key: 'age', title: '年龄', width: 100, align: 'center' },
{ key: 'actions', title: '操作', width: 220, align: 'center' }
]
const actionData = ref(Array.from({ length: 12 }).map((_, i) => ({
id: i + 1,
name: `用户${i + 1}`,
age: 18 + (i % 10),
actions: ''
})))
function onView(row: any) {
console.log('查看:', row)
}
function onEdit(row: any) {
console.log('编辑:', row)
}
function onDelete(row: any) {
console.log('删除:', row)
actionData.value = actionData.value.filter(r => r.id !== row.id)
}
</script>
<template>
<div class="table-demo">
<c-table
:columns="actionColumns"
:data="actionData"
:total="actionData.length"
:page-sizes="[5, 10, 20]"
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
>
<!-- 自定义名称列:加粗显示 -->
<template #name="{ row }">
<strong>{{ row.name }}</strong>
</template>
<!-- 自定义操作列:按钮组 -->
<template #actions="{ row }">
<c-button size="small" type="primary" class="action-btn" @click="onView(row)">查看</c-button>
<c-button size="small" type="warning" class="action-btn" @click="onEdit(row)">编辑</c-button>
<c-button size="small" type="danger" plain class="action-btn" @click="onDelete(row)">删除</c-button>
</template>
</c-table>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const currentPage = ref(1)
const pageSize = ref(10)
</script>
<style>
.table-demo .action-btn + .action-btn {
margin-left: 8px;
}
</style>
Props
columns: Array<{ key: string; title: string; width?: number; align?: 'left'|'center'|'right' }>
列定义data: Array<Record<string, any>>
表格数据total: number
数据总条数,用于分页的显示与计算currentPage: number
当前页(支持v-model:currentPage
)pageSize: number
每页数量(支持v-model:pageSize
)showPagination: boolean
是否显示分页(即使total
为 0)pageSizes: number[]
可选页大小列表showSizeChanger: boolean
是否显示页大小切换器showTotal: boolean
是否显示总条数文案totalText: string
总条数字符串模板,支持{total}
占位符emptyText: string
空数据占位文案rowKey: string
行唯一键(用于提升渲染效率)size: 'small' | 'medium' | 'large'
表格尺寸(默认:medium
)columnResizable: boolean
是否开启列宽拖拽(默认:false
)minColumnWidth: number
最小列宽(px,默认:60
)maxColumnWidth: number
最大列宽(px,默认:600
)scrollX: boolean
是否启用横向滚动(默认:true
)。开启后内部表格min-width
等于所有列宽总和,可出现横向滚动条。height: number | string
表格可视高度(默认:300px
)。超过该高度时仅内容区(tbody
)滚动,表头默认固定。stickyHeader: boolean
是否固定表头(默认:true
)。固定后,垂直滚动仅发生在内容区,表头保持不动。
Emits
update:currentPage
当前页变更update:pageSize
页大小变更pageChange
分页变化(包含当前页与页大小)
事件用法示例
在表格上监听 pageChange
(或 update:currentPage
/ update:pageSize
)以处理分页变化。
vue
<script setup lang="ts">
import { ref } from "vue";
const columns = [
{ key: "id", title: "ID", width: 80, align: "center" },
{ key: "name", title: "名称" },
{ key: "age", title: "年龄", width: 100, align: "center" },
];
const allData = Array.from({ length: 50 }).map((_, i) => ({
id: i + 1,
name: `用户${i + 1}`,
age: 18 + (i % 10),
}));
const currentPage = ref(1);
const pageSize = ref(10);
function onPageChange(page: number, size: number) {
console.log("分页变化", { page, size });
}
</script>
<template>
<c-table
:columns="columns"
:data="allData"
:total="allData.length"
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
@pageChange="onPageChange"
/>
<!-- 等价:
<c-table
...
@update:currentPage="(p)=>currentPage=p"
@update:pageSize="(s)=>pageSize=s"
/>
-->
</template>
服务端分页(示例)
通过监听 pageChange
,请求服务端接口加载当前页数据,并更新 data
与 total
。
vue
<script setup lang="ts">
import { ref } from "vue";
const columns = [
{ key: "id", title: "ID", width: 80, align: "center" },
{ key: "name", title: "名称" },
{ key: "age", title: "年龄", width: 100, align: "center" },
];
const data = ref<any[]>([]);
const total = ref(0);
const currentPage = ref(1);
const pageSize = ref(10);
async function fetchList(page: number, size: number) {
// 示例:模拟请求,可替换为真实接口
await new Promise((r) => setTimeout(r, 300));
const mockTotal = 123;
const start = (page - 1) * size;
const pageData = Array.from({ length: size }).map((_, i) => ({
id: start + i + 1,
name: `用户${start + i + 1}`,
age: 18 + ((start + i) % 10),
}));
data.value = pageData;
total.value = mockTotal;
}
function onPageChange(page: number, size: number) {
fetchList(page, size);
}
// 初始化加载
fetchList(currentPage.value, pageSize.value);
</script>
<template>
<c-table
:columns="columns"
:data="data"
:total="total"
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
@pageChange="onPageChange"
:show-pagination="true"
/>
</template>
最佳实践
- 设置
rowKey
,确保每行有稳定唯一键,提升渲染稳定性。 - 需要列宽拖拽时,为列设置像素宽度(如
80
或"120px"
)。 - 大量自定义插槽时,尽量减少复杂计算或频繁状态更新,避免性能问题。
- 分页与数据请求分离:通过
pageChange
驱动请求,响应后更新data
与total
。
常见问题
- 为什么列宽拖拽不生效?拖拽仅支持像素宽度,百分比或自适应宽度无法拖拽。
total
为 0 时分页不显示?可以通过showPagination
强制显示。- 列对齐不生效?检查列定义中的
align
是否设置为left|center|right
。
动态列显示/隐藏
通过维护可见列的 key
列表,动态计算传入的 columns
。
vue
<script setup lang="ts">
import { ref, computed } from "vue";
const baseColumns = [
{ key: "id", title: "ID", width: 80, align: "center" },
{ key: "name", title: "名称", width: 160 },
{ key: "age", title: "年龄", width: 100, align: "center" },
{ key: "address", title: "地址", width: 240 },
];
const visibleKeys = ref<string[]>(baseColumns.map((c) => c.key));
const columnsDyn = computed(() =>
baseColumns.filter((c) => visibleKeys.value.includes(c.key))
);
function onToggle(key: string, checked: boolean) {
const set = new Set(visibleKeys.value);
if (checked) set.add(key);
else set.delete(key);
visibleKeys.value = Array.from(set);
}
const dataDyn = Array.from({ length: 12 }).map((_, i) => ({
id: i + 1,
name: `用户${i + 1}`,
age: 18 + (i % 10),
address: `城市-${(i % 5) + 1}`,
}));
</script>
<template>
<div class="table-dynamic">
<div class="controls">
<label v-for="c in baseColumns" :key="c.key">
<input
type="checkbox"
:checked="visibleKeys.includes(c.key)"
@change="onToggle(c.key, ($event.target as HTMLInputElement).checked)"
/>
{{ c.title }}
</label>
</div>
<c-table :columns="columnsDyn" :data="dataDyn" :total="dataDyn.length" />
</div>
</template>
<style>
.table-dynamic .controls {
margin-bottom: 8px;
}
.table-dynamic .controls label {
margin-right: 12px;
}
</style>
列顺序拖动(基于外部状态)
通过 HTML5 拖拽交互,维护列顺序 order
,动态生成传入的 columns
。
vue
<script setup lang="ts">
import { ref, computed } from "vue";
const baseColumns = [
{ key: "id", title: "ID", width: 80, align: "center" },
{ key: "name", title: "名称", width: 160 },
{ key: "age", title: "年龄", width: 100, align: "center" },
{ key: "address", title: "地址", width: 240 },
];
const order = ref<string[]>(baseColumns.map((c) => c.key));
const columnsDragOrder = computed(() =>
order.value.map((k) => baseColumns.find((c) => c.key === k)!).filter(Boolean)
);
let dragKey: string | null = null;
function onDragStart(key: string) {
dragKey = key;
}
function onDragOver(e: DragEvent) {
e.preventDefault();
}
function onDrop(targetKey: string) {
if (!dragKey) return;
const arr = [...order.value];
const from = arr.indexOf(dragKey);
const to = arr.indexOf(targetKey);
if (from === -1 || to === -1) return;
arr.splice(to, 0, arr.splice(from, 1)[0]);
order.value = arr;
dragKey = null;
}
const data = Array.from({ length: 8 }).map((_, i) => ({
id: i + 1,
name: `用户${i + 1}`,
age: 18 + (i % 10),
address: `城市-${(i % 5) + 1}`,
}));
</script>
<template>
<div class="drag-order">
<div class="drag-list">
<span
v-for="k in order"
:key="k"
class="drag-item"
draggable="true"
@dragstart="onDragStart(k)"
@dragover="onDragOver"
@drop="onDrop(k)"
>{{ baseColumns.find((c) => c.key === k)?.title }}</span
>
</div>
<c-table :columns="columnsDragOrder" :data="data" :total="data.length" />
</div>
</template>
<style>
.drag-order .drag-list {
display: flex;
gap: 8px;
margin-bottom: 8px;
flex-wrap: wrap;
}
.drag-order .drag-item {
padding: 4px 8px;
border: 1px dashed #bbb;
border-radius: 4px;
cursor: move;
background: #fafafa;
}
.drag-order .drag-item:hover {
background: #f0f0f0;
}
</style>
固定表头与横向滚动
使用容器滚动,结合 position: sticky
固定表头。横向滚动通过设置较宽的列总宽度触发。
vue
<script setup lang="ts">
const wideColumns = [
{ key: "id", title: "ID", width: 100, align: "center" },
{ key: "name", title: "名称", width: 240 },
{ key: "dept", title: "部门", width: 240 },
{ key: "role", title: "角色", width: 240 },
{ key: "email", title: "邮箱", width: 300 },
{ key: "address", title: "地址", width: 360 },
];
const wideData = Array.from({ length: 30 }).map((_, i) => ({
id: i + 1,
name: `用户${i + 1}`,
dept: `部门-${(i % 4) + 1}`,
role: `角色-${(i % 3) + 1}`,
email: `user${i + 1}@example.com`,
address: `城市-${(i % 5) + 1}`,
}));
// 内置横向滚动示例:列更多、总宽更大
const wideColumns2 = [
{ key: "id", title: "ID", width: 100, align: "center" },
{ key: "name", title: "名称", width: 240 },
{ key: "dept", title: "部门", width: 240 },
{ key: "role", title: "角色", width: 240 },
{ key: "email", title: "邮箱", width: 300 },
{ key: "address", title: "地址", width: 360 },
{ key: "city", title: "城市", width: 240 },
{ key: "country", title: "国家", width: 240 },
{ key: "zip", title: "邮编", width: 200 },
];
const wideData2 = Array.from({ length: 30 }).map((_, i) => ({
id: i + 1,
name: `用户${i + 1}`,
dept: `部门-${(i % 4) + 1}`,
role: `角色-${(i % 3) + 1}`,
email: `user${i + 1}@example.com`,
address: `城市-${(i % 5) + 1}`,
city: `城市-${(i % 10) + 1}`,
country: `国家-${(i % 7) + 1}`,
zip: `${100000 + i}`,
}));
</script>
<template>
<div class="table-sticky-scroll">
<c-table :columns="wideColumns" :data="wideData" :total="wideData.length" />
</div>
</template>
<style>
.table-sticky-scroll {
max-height: 220px;
overflow: auto;
border: 1px solid #ebeef5;
}
.table-sticky-scroll .c-table__inner {
min-width: 1200px;
}
.table-sticky-scroll thead .c-table__th {
position: sticky;
top: 0;
z-index: 1;
background: #f8f9fb;
}
</style>
类型参考与大数据量建议
ts
// TableColumn 类型(简要)
interface TableColumn {
key: string;
title: string;
width?: number | string;
align?: "left" | "center" | "right";
render?: (row: any, index: number) => any;
}
- 大数据量建议:
- 使用分页控制每页数据量,避免一次性渲染过多行。
- 对列宽进行合理约束,结合横向滚动避免内容拥挤。
- 如需展示 500+ 行,建议采用虚拟列表技术(目前组件未内置,可自行集成)。