TablePro 表格组件
基于 TDesign Vue Next 的增强表格组件,提供搜索表单、分页、排序、过滤等高级功能。
功能特性
- 🔍 智能搜索表单 - 自动根据列配置生成搜索表单
- 📄 分页支持 - 内置分页功能,支持前端和后端分页
- 🔄 数据请求 - 支持异步数据请求和自动加载状态
- 📊 排序过滤 - 支持列排序和数据过滤
- 🎨 插槽扩展 - 丰富的插槽支持,灵活定制表格头部和内容
- 🔧 类型安全 - 完整的 TypeScript 类型定义
- 📱 响应式布局 - 搜索表单自适应容器宽度
基础使用
Center Header
Left Header
Right Header
ID | Name | Age | Address | Email | Phone | Actions |
---|---|---|---|---|---|---|
1 | John Doe | 30 | 123 Main St | - | - | - |
2 | Jane Smith | 25 | 456 Elm St | - | - | - |
3 | Alice Johnson | 28 | 789 Maple Ave | - | - | - |
4 | Bob Brown | 35 | 101 Pine Rd | - | - | - |
5 | Charlie White | 22 | 202 Oak St | - | - | - |
6 | Diana Green | 27 | 303 Birch Blvd | - | - | - |
7 | Ethan Blue | 32 | 404 Cedar Ct | - | - | - |
8 | Fiona Black | 29 | 505 Spruce Dr | - | - | - |
9 | George Gray | 31 | 606 Willow Way | - | - | - |
10 | Hannah Yellow | 26 | 707 Cherry Ln | - | - | - |
11 | Ian Purple | 34 | 808 Ash St | - | - | - |
12 | Julia Orange | 23 | 909 Palm Pl | - | - | - |
13 | Kevin Pink | 30 | 1010 Magnolia Ave | - | - | - |
14 | Laura Cyan | 28 | 1111 Peach St | - | - | - |
15 | Mike Red | 33 | 1212 Maple St | - | - | - |
16 | Nina Teal | 24 | 1313 Cedar St | - | - | - |
17 | Oscar Silver | 36 | 1414 Oak St | - | - | - |
18 | Paula Gold | 21 | 1515 Pine St | - | - | - |
19 | Quinn Bronze | 29 | 1616 Birch St | - | - | - |
20 | Rita Copper | 32 | 1717 Spruce St | - | - | - |
共 0 条数据
50 条/页
- 1
查看代码
vue
<template>
<div class="base-table-container">
<TablePro :columns="columns" row-key="id" :data="data">
<template #tableHeaderCenter>
<div>Center Header</div>
</template>
<template #tableHeaderLeft>
<div>Left Header</div>
</template>
<template #tableHeaderRight>
<div>Right Header</div>
</template>
</TablePro>
</div>
</template>
<script setup lang="ts">
import type { ProTableCol } from 't-design-pro'
import { TablePro } from 't-design-pro'
import { useData } from 'vitepress'
import { ref, watch } from 'vue'
const { isDark } = useData()
watch(
isDark,
(newVal) => {
document.documentElement.setAttribute('theme-mode', newVal ? 'dark' : 'light')
},
{
immediate: true
}
)
const columns = ref<ProTableCol[]>([
{
title: 'ID',
colKey: 'id',
width: 100,
search: true,
fixed: 'left'
},
{
title: 'Name',
colKey: 'name',
width: 200,
search: true
},
{
title: 'Age',
colKey: 'age',
width: 100,
search: true
},
{
title: 'Address',
colKey: 'address',
width: 300,
search: true
},
{
title: 'Email',
colKey: 'email',
width: 200,
search: true
},
{
title: 'Phone',
colKey: 'phone',
width: 150,
search: true
},
{
title: 'Actions',
colKey: 'operation',
width: 150,
fixed: 'right'
}
])
const data = ref([
{ id: 1, name: 'John Doe', age: 30, address: '123 Main St' },
{ id: 2, name: 'Jane Smith', age: 25, address: '456 Elm St' },
{ id: 3, name: 'Alice Johnson', age: 28, address: '789 Maple Ave' },
{ id: 4, name: 'Bob Brown', age: 35, address: '101 Pine Rd' },
{ id: 5, name: 'Charlie White', age: 22, address: '202 Oak St' },
{ id: 6, name: 'Diana Green', age: 27, address: '303 Birch Blvd' },
{ id: 7, name: 'Ethan Blue', age: 32, address: '404 Cedar Ct' },
{ id: 8, name: 'Fiona Black', age: 29, address: '505 Spruce Dr' },
{ id: 9, name: 'George Gray', age: 31, address: '606 Willow Way' },
{ id: 10, name: 'Hannah Yellow', age: 26, address: '707 Cherry Ln' },
{ id: 11, name: 'Ian Purple', age: 34, address: '808 Ash St' },
{ id: 12, name: 'Julia Orange', age: 23, address: '909 Palm Pl' },
{ id: 13, name: 'Kevin Pink', age: 30, address: '1010 Magnolia Ave' },
{ id: 14, name: 'Laura Cyan', age: 28, address: '1111 Peach St' },
{ id: 15, name: 'Mike Red', age: 33, address: '1212 Maple St' },
{ id: 16, name: 'Nina Teal', age: 24, address: '1313 Cedar St' },
{ id: 17, name: 'Oscar Silver', age: 36, address: '1414 Oak St' },
{ id: 18, name: 'Paula Gold', age: 21, address: '1515 Pine St' },
{ id: 19, name: 'Quinn Bronze', age: 29, address: '1616 Birch St' },
{ id: 20, name: 'Rita Copper', age: 32, address: '1717 Spruce St' }
])
</script>
<style scoped>
.base-table-container {
height: 700px;
}
</style>
动态请求数据
Name | Age | Address |
---|---|---|
暂无数据 |
共 0 条数据
50 条/页
- 1
查看代码
vue
<template>
<div>
<TButton @click="refresh">刷新</TButton>
<TablePro
ref="tableRef"
:columns="columns"
row-key="id"
:loading="loading"
:request="request"
></TablePro>
</div>
</template>
<script setup lang="ts">
import { TablePro } from 't-design-pro'
import { Button as TButton } from 'tdesign-vue-next'
import { useData } from 'vitepress'
import { ref, watch } from 'vue'
import type { ProTableCol } from '@/components/Table/types'
const { isDark } = useData()
watch(
isDark,
(newVal) => {
document.documentElement.setAttribute('theme-mode', newVal ? 'dark' : 'light')
},
{
immediate: true
}
)
const columns = ref<ProTableCol[]>([
{
title: 'Name',
colKey: 'name',
width: 200
},
{
title: 'Age',
colKey: 'age',
width: 100
},
{
title: 'Address',
colKey: 'address',
width: 300
}
])
const data = [
{ id: 1, name: 'John Doe', age: 30, address: '123 Main St' },
{ id: 2, name: 'Jane Smith', age: 25, address: '456 Elm St' },
{ id: 3, name: 'Alice Johnson', age: 28, address: '789 Maple Ave' },
{ id: 4, name: 'Bob Brown', age: 35, address: '101 Pine Rd' }
]
const getData = (params: { name: string }) => {
console.log('params', params)
return new Promise<{ data: any[]; total: number }>((resolve) => {
setTimeout(() => {
resolve({
data,
total: data.length
})
}, 1500)
})
}
const loading = ref(false)
const request = async (params) => {
try {
loading.value = true
const result = await getData(params)
return {
data: result.data,
total: result.total
}
} catch {
return null
} finally {
loading.value = false
}
}
const tableRef = ref<InstanceType<typeof TablePro> | null>(null)
const refresh = () => {
tableRef.value?.refresh()
}
</script>
<style></style>
API
Props
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
request | 数据请求方法 | ProTableRequestMethod | - |
extendParams | 请求扩展参数 | ExtendParams | - |
columns | 表格列配置 | ProTableCol[] | [] |
data | 静态数据 | Array<any> | - |
rowKey | 行数据的唯一标识字段名 | string | 'id' |
cellEmptyContent | 空单元格显示内容 | string | '-' |
pagination | 分页配置 | PaginationProps | null | { defaultCurrent: 1, defaultPageSize: 50 } |
resetType | 表单重置类型 | 'initial' | 'empty' | 'initial' |
tableProps | 透传给 EnhancedTable 的属性 | ProTablePropsOmitKey | {} |
ProTableCol 列配置
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
colKey | 列标识符 | string | - |
title | 列标题 | string | TNode | - |
width | 列宽度 | number | string | - |
fixed | 固定列位置 | 'left' | 'right' | - |
hidden | 是否隐藏列 | boolean | false |
search | 搜索配置 | ProTableColSearchType | boolean | - |
cellContentEnum | 单元格内容枚举映射 | Record<string, any> | - |
cell | 自定义单元格渲染 | TNode | - |
ProTableColSearchType 搜索配置
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
key | 搜索字段名(默认使用 colKey) | string | - |
label | 搜索表单标签 | string | - |
valueType | 搜索组件类型 | SearchValueType | 't-input' |
valueEnum | 选择器选项枚举 | Record<string, any> | - |
fieldProps | 组件属性 | Record<string, any> | - |
render | 自定义渲染搜索组件 | () => VNode | - |
SearchValueType 搜索组件类型
支持的搜索组件类型:
't-input'
- 输入框't-select'
- 选择器't-date-picker'
- 日期选择器't-date-range-picker'
- 日期范围选择器VNode
- 自定义组件
方法
方法名 | 说明 | 参数 | 返回值 |
---|---|---|---|
refresh | 刷新表格数据(不重置分页) | - | - |
reset | 重置表格(重置分页到第一页) | - | - |
restSearchForm | 重置搜索表单 | FormResetParams | - |
appendTo | 新增数据到指定位置 | (key: string, newData: any) | - |
插槽
插槽名 | 说明 | 参数 |
---|---|---|
tableHeaderCenter | 表格头部中心区域 | - |
tableHeaderLeft | 表格头部左侧区域 | - |
tableHeaderRight | 表格头部右侧区域 | - |
empty | 空数据状态 | - |
事件
继承 TDesign EnhancedTable 的所有事件,主要包括:
change
- 分页、排序、过滤变化时触发select-change
- 选择变化时触发expand-change
- 展开变化时触发
高级用法
搜索表单配置
vue
<template>
<TablePro :columns="columns" :request="fetchData" />
</template>
<script setup>
const columns = [
{
title: '用户名',
colKey: 'username',
search: true // 简单搜索配置
},
{
title: '状态',
colKey: 'status',
search: {
valueType: 't-select',
valueEnum: {
active: '活跃',
inactive: '非活跃'
}
}
},
{
title: '创建时间',
colKey: 'createTime',
search: {
valueType: 't-date-range-picker',
fieldProps: {
enableTimePicker: true
}
}
}
]
</script>
自定义搜索组件
vue
<script setup>
const columns = [
{
title: '自定义搜索',
colKey: 'custom',
search: {
render: () => h(CustomComponent, {
placeholder: '请输入关键词'
})
}
}
]
</script>
数据请求方法
javascript
const fetchData = async (params) => {
const { current, pageSize, ...searchParams } = params
const response = await api.getTableData({
page: current,
size: pageSize,
...searchParams
})
return {
data: response.list,
total: response.total
}
}
表格头部插槽
vue
<template>
<TablePro :columns="columns">
<template #tableHeaderLeft>
<t-button theme="primary">新增</t-button>
</template>
<template #tableHeaderRight>
<t-button theme="default">导出</t-button>
<t-button theme="default">设置</t-button>
</template>
</TablePro>
</template>
注意事项
- 数据请求方法:
request
方法需要返回{ data: Array, total: number }
格式的数据 - 列标识符:每列必须设置唯一的
colKey
- 搜索表单:只有设置了
search
属性的列才会出现在搜索表单中 - 分页处理:组件会自动处理分页参数传递和页码管理
- 响应式布局:搜索表单会根据容器宽度自动调整列数和布局