tanstack-pro-table-vue
v1.2.3
Published
High performance Vue 3 data grid powered by TanStack Table and Virtual.
Readme
tanstack-pro-table-vue
基于 Vue 3.5、TanStack Table v8 和 TanStack Virtual 的高性能表格组件。API 尽量贴近 vxe-table 的常用写法,适合大数据列表、宽表、固定列、多级表头、自定义插槽、树形表格、表尾汇总、服务端分页和服务端排序等场景。
安装
pnpm add tanstack-pro-table-vue也可以使用 npm 或 yarn:
npm install tanstack-pro-table-vue
yarn add tanstack-pro-table-vuevue 是 peer dependency,请确保项目中使用 Vue ^3.5.0。
全局引入样式
在应用入口中引入组件样式:
import 'tanstack-pro-table-vue/style.css'例如 Vite + Vue 项目的 src/main.ts:
import { createApp } from 'vue'
import App from './App.vue'
import 'tanstack-pro-table-vue/style.css'
createApp(App).mount('#app')基础用法
<script setup lang="ts">
import { ref } from 'vue'
import { ProTable, type ProTableColumn, type ProTableExpose } from 'tanstack-pro-table-vue'
interface TradeRow {
id: string
symbol: string
side: '买入' | '卖出'
quantity: number
status: string
}
const tableRef = ref<ProTableExpose<TradeRow> | null>(null)
const rows: TradeRow[] = [
{ id: 'TRD-000001', symbol: 'AAPL', side: '买入', quantity: 100, status: '已撮合' },
{ id: 'TRD-000002', symbol: 'MSFT', side: '卖出', quantity: 200, status: '已结算' }
]
const columns: ProTableColumn<TradeRow>[] = [
{ type: 'checkbox', width: 48, fixed: 'left' },
{ type: 'seq', title: '#', width: 64, fixed: 'left' },
{ field: 'id', title: '委托编号', width: 180 },
{ field: 'symbol', title: '标的' },
{ field: 'side', title: '方向', width: 100, align: 'center' },
{ field: 'quantity', title: '数量', width: 120, align: 'right' },
{ field: 'status', title: '状态', width: 120 }
]
function scrollTop() {
tableRef.value?.scrollTo(0, 0)
}
</script>
<template>
<button @click="scrollTop">回到左上角</button>
<ProTable
ref="tableRef"
:data="rows"
:columns="columns"
row-key="id"
height="420"
theme="light"
border
stripe
/>
</template>多级表头
children 与 vxe-table 的列分组写法一致。父级列只描述分组,最终渲染和取值由叶子列决定。
const columns: ProTableColumn<TradeRow>[] = [
{
title: '基础信息',
children: [
{ field: 'id', title: '委托编号', width: 180 },
{ field: 'symbol', title: '标的', width: 140 }
]
},
{
title: '交易信息',
children: [
{ field: 'side', title: '方向', width: 100 },
{ field: 'quantity', title: '数量', width: 120, align: 'right' }
]
}
]自定义单元格和表头
支持通用插槽、按列 id 命名的插槽,也支持 vxe-table 风格的 slots 配置。
<script setup lang="ts">
const columns = [
{ field: 'symbol', title: '标的', slots: { header: 'symbolHeader' } },
{ field: 'status', title: '状态', slots: { default: 'statusCell' } }
]
</script>
<template>
<ProTable :data="rows" :columns="columns" row-key="id">
<template #symbolHeader="{ column }">
<strong>{{ column.title }}</strong>
</template>
<template #statusCell="{ value }">
<span class="status-tag">{{ value }}</span>
</template>
</ProTable>
</template>大数据虚拟滚动
默认开启行虚拟滚动,只渲染可视区域和 overscan 范围。
<ProTable
:data="bigRows"
:columns="columns"
row-key="id"
height="600"
:row-config="{ height: 42 }"
:overscan="8"
/>大数据性能建议:
| 场景 | 推荐配置 | 说明 |
| --- | --- | --- |
| 极限大数据浏览 | :row-config="{ height: 42 }" | 固定行高性能最好,虚拟滚动计算最稳定。 |
| 长文本需要换行 | :row-config="{ height: 42, autoHeight: true }" | 仍然只渲染可视区域,但需要测量可视行真实高度,极限性能不如固定行高。 |
| 宽表 | 显式设置主要列宽 | 表格会显示底部横向滚动条,固定列和宽表更容易拖动。 |
服务端分页
分页是独立组件区域,只负责展示页码并触发事件,不会在组件内部切分 data。页码从 1 开始。
<ProTable
:data="rows"
:columns="columns"
row-key="id"
:pager-config="{
currentPage,
pageSize,
total,
placement: 'bottom-right',
layout: ['total', 'sizes', 'first', 'prev', 'pager', 'next', 'last', 'jumper']
}"
@page-change="loadPage"
/>服务端排序
推荐服务端排序。默认单字段排序,设置 sortConfig.multiple 可开启多字段排序。
<ProTable
:data="rows"
:columns="columns"
row-key="id"
:sort-config="{ remote: true, multiple: true, orders: ['asc', 'desc', null] }"
@sort-change="loadSortedData"
/>orders 控制排序循环:
['asc', 'desc']:升序、降序循环,不清空。['asc', 'desc', null]:升序、降序、清空循环。
需要主动清空排序时:
tableRef.value?.clearSorting()树形表格
<ProTable
:data="treeRows"
:columns="columns"
row-key="id"
:tree-config="{ children: 'children', indent: 18, expandAll: false }"
/>标记树节点列:
const columns = [
{ field: 'name', title: '节点名称', treeNode: true },
{ field: 'owner', title: '负责人' }
]合并单元格
通过 spanMethod 返回 rowspan 和 colspan。返回 0 表示当前单元格被其它单元格覆盖。
<ProTable
:data="rows"
:columns="columns"
row-key="id"
:span-config="{ maxRowspan: 8 }"
:span-method="({ rowIndex, columnIndex }) => {
if (columnIndex === 0 && rowIndex % 3 === 0) return { rowspan: 3, colspan: 1 }
if (columnIndex === 0) return { rowspan: 0, colspan: 0 }
return { rowspan: 1, colspan: 1 }
}"
/>大数据合并时建议设置 spanConfig.maxRowspan,用于限制虚拟滚动可视区域向上查找合并源单元格的范围。
主题和国际化
内置暗色和亮色:
<ProTable theme="dark" />
<ProTable theme="light" />可通过 themeVars 覆盖当前实例的主题变量:
<ProTable
theme="light"
:theme-vars="{
accent: '#e11d48',
hoverBg: '#fff1f2',
currentBg: '#ffe4e6',
selectedBg: '#fce7f3',
scrollbarThumb: '#fb7185',
pagerActiveBg: '#e11d48',
checkboxColor: '#e11d48'
}"
/>内置中文和英文:
<ProTable locale="zh-CN" />
<ProTable locale="en-US" />也可以覆盖文案:
<ProTable
:locale-config="{
emptyText: '没有查询到数据',
pagerTotal: (total) => `共 ${total} 条`
}"
/>常用 Props
| 属性 | 类型 | 说明 |
| --- | --- | --- |
| data | TData[] | 表格数据。 |
| columns | ProTableColumn<TData>[] | 列配置,支持 field/title/type/children/slots。 |
| rowKey | string \| number \| (row, index) => string \| number | 行唯一键。 |
| height | number \| string | 表格高度;不传或 auto 为流体高度,传数字、百分比或 calc() 时内部滚动。 |
| align / headerAlign | 'left' \| 'center' \| 'right' | 默认单元格/表头对齐,列配置优先级更高。 |
| border / stripe / loading | boolean | 边框、斑马纹、加载态。 |
| virtual | boolean | 是否开启行虚拟滚动,默认开启。 |
| overscan | number | 虚拟滚动可视区外额外渲染行数。 |
| rowConfig | ProTableRowConfig | 行配置,如 height、autoHeight、isCurrent。 |
| sortConfig | ProTableSortConfig | 排序配置。 |
| pagerConfig | false \| ProTablePagerConfig | 分页配置。 |
| treeConfig | false \| ProTableTreeConfig | 树形表格配置。 |
| spanMethod | ProTableSpanMethod<TData> | 合并单元格方法。 |
| spanConfig | ProTableSpanConfig | 合并单元格配置。 |
| showFooter | boolean | 是否显示表尾。 |
| footerData / footerMethod | Array<Record<string, unknown>> \| Function | 表尾数据或汇总方法。 |
| theme | 'dark' \| 'light' | 内置主题。 |
| themeVars | ProTableThemeVars | 主题变量覆盖。 |
| locale | 'zh-CN' \| 'en-US' | 国际化语言。 |
| localeConfig | Partial<ProTableLocaleConfig> | 国际化文案覆盖。 |
Column 常用配置
| 属性 | 类型 | 说明 |
| --- | --- | --- |
| type | 'seq' \| 'index' \| 'checkbox' \| 'selection' \| 'radio' \| 'expand' \| 'html' | 列类型。 |
| field / prop | string | 数据字段。 |
| title / label | string | 列标题。 |
| children | ProTableColumn[] | 多级表头。 |
| width / minWidth / maxWidth | number \| string | 列宽。 |
| fixed | 'left' \| 'right' | 固定列。 |
| align / headerAlign / footerAlign | 'left' \| 'center' \| 'right' | 单元格、表头、表尾对齐。 |
| sortable | boolean | 是否允许排序。 |
| visible | boolean | 控制列显示隐藏。 |
| treeNode | boolean | 树形节点列。 |
| showOverflow / showHeaderOverflow / showFooterOverflow | boolean \| 'ellipsis' \| 'title' \| 'tooltip' | 内容溢出省略。 |
| formatter | (params) => unknown | 单元格格式化。 |
| slots | { default?, header?, footer? } | vxe-table 风格插槽配置。 |
暴露方法
通过 ref 获取:
const tableRef = ref<ProTableExpose<Row> | null>(null)| 方法 | 说明 |
| --- | --- |
| clearSelection() | 清空选择。 |
| toggleAllRowsSelected(value?) | 全选或取消全选。 |
| getSelectedRows() | 获取当前选中行数据。 |
| getSorting() | 获取当前排序状态。 |
| clearSorting() | 清空全部排序。 |
| scrollToIndex(index) | 滚动到指定行索引。 |
| scrollTo(x, y) | 滚动到指定横向和纵向像素位置。 |
| setColumnVisible(columnId, visible) | 设置单列显隐。 |
| showColumn(columnId) / hideColumn(columnId) | 显示或隐藏单列。 |
| setColumnsVisible(columnIds, visible) | 批量设置列显隐。 |
| resetColumnVisibility() | 重置通过方法设置的列显隐。 |
事件
| 事件 | 说明 |
| --- | --- |
| sort-change | 排序变化,参数为 TanStack SortingState。 |
| page-change | 分页变化,包含 currentPage/pageIndex/pageSize/total/pageCount。 |
| selection-change | 多选变化,参数为选中行数据。 |
| row-click | 行点击。 |
| cell-click | 单元格点击。 |
| current-change | 当前行变化。 |
| keyboard-cell-change | 键盘导航单元格变化。 |
类型导入
import type {
ProTableColumn,
ProTableExpose,
ProTableProps,
ProTableRowConfig,
ProTablePagerConfig,
ProTableSortConfig,
ProTableThemeVars,
ProTableSpanMethod
} from 'tanstack-pro-table-vue'