更新记录
1.0.0(2026-04-21)
首次发布
- 基于 Canvas 2D 的高性能表格组件,支持 H5 和微信小程序
- 支持固定列(
fixed: 'left' | 'right')与固定行(fixedRows) - 支持列宽 / 行高拖拽调整(
useColRowResize) - 支持虚拟滚动:行虚拟(超过阈值自动开启)、列虚拟(列数 > 10 自动开启)
- 支持单元格合并(
options.spanMethod) - 支持多级表头(
ColumnNode.children) - 支持行选择:复选框 / 单选(
rowSelection) - 支持区域框选(
enableSelection) - 支持排序(
ColumnNode.sortable,受控 / 非受控模式) - 支持树形数据展开 / 折叠(
treeProps)及懒加载 - 支持分页配置(
pagination) - 支持 Tooltip 悬浮提示(
ColumnNode.tooltip) - 支持自定义单元格渲染(
ColumnNode.cellRender) - 支持操作按钮列(
ColumnNode.actionButtons) - 支持加载状态(
loading)与空状态(EmptyLayer) - 支持条纹行、悬停高亮、列悬停高亮
- 支持文本溢出处理:截断 / 省略号 / 自动折行(
cellOverflow) - 支持自定义 Overlay 绘制(
bodyOverlayDraw/fixedTopOverlayDraw/fixedBottomOverlayDraw) - 暴露 Ref 方法:
scrollTo、scrollToRow、scrollToColumn、getSelectionRange、clearSelection、getSelectedRowKeys、clearRowSelection、getSortState、resetSort、getExpandedKeys、setExpandedKeys、redraw
平台兼容性
uni-app(3.7.6)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| - | √ | √ | √ | - | - | - | - | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | - | - | - | - | - | - | - | - | - | - | - |
其他
| 多语言 | 暗黑模式 | 宽屏模式 |
|---|---|---|
| × | × | √ |
# pro-table
pro-table 是一个基于单 canvas 分层渲染的高性能表格组件,面向 uni-app + Vue 3 场景,兼容 H5 和小程序端。
它不是 DOM 表格,而是把表头、表体、固定列、固定行、阴影、选区、tooltip、拖拽指示线等内容拆成多个 layer 绘制到同一张 canvas 上,因此更适合大数据量、固定列、虚拟滚动、复杂自定义绘制等场景。
特性
- 单 canvas 分层渲染
- H5 / 小程序双端适配
- 固定表头、固定列、固定行
- 行虚拟滚动、主区列虚拟滚动
- 单元格选区
- 行选择 checkbox / radio
- 列宽拖拽、行高拖拽
- 树形数据展开 / 折叠 / 懒加载
- 客户端排序
- 分页数据切片
- 悬浮提示 tooltip
- 自定义单元格绘制、覆盖层绘制、操作按钮
- 单元格横向 / 纵向合并
快速开始
<template>
<view class="table-wrap">
<pro-table
ref="tableRef"
:columns="columns"
:data="data"
:options="options"
@cell-click="onCellClick"
/>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import ProTable from '@/uni_modules/pro-table/components/pro-table/pro-table.vue'
import type {
ColumnNode,
ProTableOptions,
RowData,
} from '@/uni_modules/pro-table'
interface UserRow extends RowData {
id: number
name: string
dept: string
salary: number
}
const tableRef = ref<any>(null)
const columns: ColumnNode[] = [
{ key: 'id', title: 'ID', width: 80, cellAlign: 'center', headerAlign: 'center' },
{ key: 'name', title: '姓名', width: 120 },
{ key: 'dept', title: '部门', width: 140 },
{ key: 'salary', title: '薪资', width: 120, cellAlign: 'right', sortable: true },
]
const data = ref<UserRow[]>([
{ id: 1, name: '张三', dept: '研发', salary: 12000 },
{ id: 2, name: '李四', dept: '产品', salary: 15000 },
])
const options: ProTableOptions = {
fontSize: 13,
padding: [8, 10],
stripedBgColor: '#fafafa',
}
function onCellClick(payload: any) {
console.log('cell-click', payload)
}
</script>
<style scoped>
.table-wrap {
height: 600px;
}
</style>
组件参数
Props
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| columns | ColumnNode[] |
必填 | 列定义,支持多级表头、固定列、排序、tooltip、自定义 render、单元格合并 |
| data | T[] |
[] |
表体数据 |
| options | ProTableOptions |
undefined |
视觉和交互选项 |
| fixedRows | FixedRowDef[] |
undefined |
固定行定义,同时支持顶部和底部固定行 |
| enableStriped | boolean |
false |
是否启用斑马纹 |
| enableHover | boolean |
true |
是否启用行 hover |
| enableColHover | boolean |
false |
是否启用列 hover |
| enableSelection | boolean |
false |
是否启用单元格框选 |
| rowSelection | RowSelectionConfig |
undefined |
行选择配置,启用后会自动注入选择列 |
| selectedRowKeys | number[] |
undefined |
受控行选择值。注意这里实际是“当前页行索引数组”,不是业务 rowKey |
| bodyOverlayDraw | (payload: OverlayDrawPayload) => void |
undefined |
表体覆盖层自定义绘制 |
| fixedTopOverlayDraw | (payload: OverlayDrawPayload) => void |
undefined |
顶部固定行覆盖层自定义绘制 |
| fixedBottomOverlayDraw | (payload: OverlayDrawPayload) => void |
undefined |
底部固定行覆盖层自定义绘制 |
| loading | boolean |
false |
加载态,开启后显示 loading layer 并阻止滚动交互 |
| treeProps | TreeConfig |
undefined |
树形表格配置 |
| pagination | PaginationConfig |
undefined |
分页配置。组件只负责分页逻辑和事件,不内置分页器 UI |
Props 详细说明
columns
- 作用:描述整张表的列结构,是最核心的输入参数
- 影响范围:表头结构、列宽、固定列、排序、tooltip、自定义单元格绘制、单元格合并都由它决定
- 使用建议:
key必须稳定且唯一,避免在运行时频繁修改列对象结构
data
- 作用:表格主体行数据
- 数据要求:每一项都是一个对象,字段名通常与列
key对应 - 额外能力:除业务字段外,还可以内联
__resizable__、__minHeight__、__maxHeight__等控制字段 - 更新建议:优先替换数组引用,而不是原地深改对象
options
- 作用:统一控制视觉样式和部分交互细节
- 典型用途:边框颜色、背景色、hover 色、字体大小、内边距、选区颜色、拖拽手柄显示
- 适用场景:想整体换风格时优先改这里,而不是在每列里单独覆盖
fixedRows
- 作用:定义固定在表头下方或底部的特殊行
- 典型用途:汇总行、合计行、说明行、固定提示行
- 数据结构:每一项都要显式声明
position: 'top' | 'bottom' - 能力范围:支持按列覆写渲染,也支持固定行内部单元格合并
enableStriped
- 作用:开启后按奇偶行绘制斑马纹背景
- 注意:只是视觉层面的辅助识别,不影响数据和事件
enableHover
- 作用:是否高亮当前悬浮行
- 平台差异:H5 主要响应鼠标悬浮,小程序依赖触摸交互流程
enableColHover
- 作用:是否高亮当前悬浮列
- 适用场景:强调列阅读对齐,例如财务表、对比表
enableSelection
- 作用:开启后可拖拽选择单元格区域
- 注意:这是“单元格框选”,和
rowSelection的“行勾选”是两套独立能力
rowSelection
- 作用:开启行级单选或多选能力
- 具体行为:组件会自动在最左侧插入一列选择列
- 注意:当前实现返回的是“当前页索引”,不是业务主键
selectedRowKeys
- 作用:行选择的受控值
- 实际含义:这里的数组成员不是 rowKey,而是当前分页结果中的行下标
- 适用场景:父组件完全接管行选择状态时使用
bodyOverlayDraw / fixedTopOverlayDraw / fixedBottomOverlayDraw
- 作用:在既有表格绘制完成后,再追加一层自定义图形
- 适用场景:趋势线、热点标记、角标、辅助线、状态点、业务注释
- 区别:三个回调分别作用于表体、顶部固定行、底部固定行区域
loading
- 作用:显示加载层,并阻止常规交互
- 适用场景:接口请求中、局部数据切换中、懒加载等待中
treeProps
- 作用:开启树形表格能力
- 适用场景:目录树、组织架构、层级账目、主从明细
- 能力范围:支持默认展开、指定展开、懒加载、缩进列配置
pagination
- 作用:开启组件内部的数据切片逻辑
- 注意:它不渲染分页器,只保存分页状态并对当前数据做 slice
- 适用场景:你自己在页面外部渲染分页栏,再通过 ref 方法或响应式配置联动
Events
| 事件名 | 回调参数 | 说明 |
|---|---|---|
| cell-click | { row, rowIndex, colKey, value, isHeader, fixedRow?, localX?, localY? } |
点击单元格或表头时触发。点击表头排序列时,会先切换排序再触发该事件 |
| selection-change | { range: SelectionRange \| null } |
选区拖拽过程中持续触发 |
| selection-end | { range: SelectionRange \| null } |
选区拖拽结束时触发 |
| row-select-change | { indices: number[]; rows: T[] } |
行选择变化。indices 为当前分页切片内的索引 |
| update:selectedRowKeys | number[] |
配合 v-model:selectedRowKeys 使用 |
| col-resize | { key: string; width: number } |
列宽拖拽结束时触发 |
| row-resize | { rowIndex: number; height: number } |
行高拖拽结束时触发 |
| sort-change | SortState |
排序变化 |
| load-more | 无 | 滚动到底部附近或内容不足填满容器时触发 |
| page-change | { page: number; pageSize: number } |
调用分页方法或切换页大小时触发 |
事件参数详细说明
cell-click
{
row: T | null
rowIndex: number
colKey: string
value: any
isHeader: boolean
fixedRow?: 'top' | 'bottom'
localX?: number
localY?: number
}
| 字段 | 含义 |
|---|---|
| row | 被点击的行数据。点击表头时为 null |
| rowIndex | 行索引。表头点击时通常为 -1,表体点击时为当前数据索引 |
| colKey | 被点击列的 key |
| value | 当前单元格的值,等价于 row?.[colKey] |
| isHeader | 是否点击的是表头 |
| fixedRow | 如果点击的是固定行单元格,这里会标记 'top' 或 'bottom' |
| localX | 指针在当前单元格内部的相对 X 坐标,可用于判断点到了单元格内部哪个子区域 |
| localY | 指针在当前单元格内部的相对 Y 坐标 |
适用场景:
- 统一处理普通单元格点击
- 区分表头点击和表体点击
- 在自定义 render 中根据
localX/localY做更细粒度交互
selection-change / selection-end
{
range: SelectionRange | null
}
| 字段 | 含义 |
|---|---|
| range | 当前选区。为 null 代表没有有效选区 |
区别:
selection-change在拖拽过程中持续触发,适合实时展示状态selection-end只在拖拽完成后触发,适合做最终提交或复制逻辑
row-select-change
{
indices: number[]
rows: T[]
}
| 字段 | 含义 |
|---|---|
| indices | 当前页中被选中的行索引数组 |
| rows | 与 indices 对应的行数据数组 |
注意:这里不是全量数据索引,也不是业务 id。
col-resize
{
key: string
width: number
}
| 字段 | 含义 |
|---|---|
| key | 被调整宽度的列 key |
| width | 调整结束后的列宽 |
row-resize
{
rowIndex: number
height: number
}
| 字段 | 含义 |
|---|---|
| rowIndex | 被调整高度的 body 行索引 |
| height | 调整结束后的最终行高 |
sort-change
排序回调返回 SortState:
key:当前参与排序的列 keyorder:当前排序方向,可能是'asc'、'desc'或null
page-change
{
page: number
pageSize: number
}
| 字段 | 含义 |
|---|---|
| page | 切换后的页码,从 1 开始 |
| pageSize | 切换后的每页条数 |
Ref 方法
组件通过 defineExpose 暴露了一组实例方法,推荐配合模板 ref 调用。
interface ProTableInstance {
scheduleRender(): void
recalcLayout(): void
scrollToRow(rowIndex: number): void
scrollToColumn(colKey: string): void
scrollTo(x?: number, y?: number): void
selectRows(indices: number[]): void
deselectRows(indices: number[]): void
selectAll(): void
deselectAll(): void
getSelectedRowIndices(): number[]
getSelection(): SelectionRange | null
clearSelection(): void
getSortState(): SortState
setSortState(state: SortState): void
getScrollLeft(): number
getScrollTop(): number
toggleExpand(rowKey: string | number): void
expandAll(): void
collapseAll(): void
getExpandedKeys(): Array<string | number>
goTo(page: number): void
prevPage(): void
nextPage(): void
setPageSize(size: number): void
getCurrentPage(): number
getPageCount(): number
getTotal(): number
}
方法说明
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
| scheduleRender | 无 | void |
手动请求下一帧重绘 |
| recalcLayout | 无 | void |
重新计算布局,并自动夹紧滚动位置 |
| scrollToRow | rowIndex: number |
void |
滚动到指定 body 行,使该行进入可视区 |
| scrollToColumn | colKey: string |
void |
滚动到指定主区列。固定列不会参与横向滚动 |
| scrollTo | x?: number, y?: number |
void |
直接设置横纵滚动位置 |
| selectRows | indices: number[] |
void |
追加选中指定索引 |
| deselectRows | indices: number[] |
void |
取消指定索引 |
| selectAll | 无 | void |
全选当前页数据 |
| deselectAll | 无 | void |
清空选择 |
| getSelectedRowIndices | 无 | number[] |
获取当前已选中的当前页索引 |
| getSelection | 无 | SelectionRange \| null |
获取当前单元格选区 |
| clearSelection | 无 | void |
清空选区 |
| getSortState | 无 | SortState |
获取当前排序状态 |
| setSortState | state: SortState |
void |
直接设置排序状态并重绘 |
| getScrollLeft | 无 | number |
获取当前横向滚动位置 |
| getScrollTop | 无 | number |
获取当前纵向滚动位置 |
| toggleExpand | rowKey: string \| number |
void |
切换树节点展开状态 |
| expandAll | 无 | void |
展开全部树节点 |
| collapseAll | 无 | void |
折叠全部树节点 |
| getExpandedKeys | 无 | Array<string \| number> |
获取当前已展开 rowKey 集合 |
| goTo | page: number |
void |
翻到指定页 |
| prevPage | 无 | void |
上一页 |
| nextPage | 无 | void |
下一页 |
| setPageSize | size: number |
void |
设置每页条数,并重置到第 1 页 |
| getCurrentPage | 无 | number |
获取当前页码 |
| getPageCount | 无 | number |
获取总页数 |
| getTotal | 无 | number |
获取总条数 |
方法参数与行为说明
scheduleRender()
- 含义:请求组件在下一帧重新绘制
- 什么时候用:外部数据没有变,但你知道自定义覆盖层或内部显示状态需要刷新时
- 注意:它只负责重绘,不负责重新计算布局
recalcLayout()
- 含义:重新计算列宽、行高、总宽高、固定区宽度等布局信息
- 什么时候用:容器尺寸变化、列定义变化、你手动修改了需要影响布局的数据时
- 补充:内部会顺带把滚动位置限制到合法范围,避免空白区域
scrollToRow(rowIndex)
- 参数含义:
rowIndex是 body 区数据索引,从0开始 - 行为:若目标行已在可视区内,不会多余滚动;若越界则直接忽略
- 注意:这里不支持传固定行索引,也不是业务主键
scrollToColumn(colKey)
- 参数含义:
colKey是你在columns中定义的列 key - 行为:只会滚动主区列;如果目标列本身是固定列,不会产生横向滚动效果
- 适用场景:表单校验后快速跳到某一列、联动定位某列
scrollTo(x, y)
- 参数含义:
x是横向滚动值,y是纵向滚动值,单位都是像素 - 行为:任一参数传
undefined表示该方向保持不变 - 补充:内部会自动夹紧到合法滚动范围
selectRows(indices)
- 参数含义:
indices是当前页内需要追加选中的行索引数组 - 行为:是“追加选中”,不会先清空已有选择
deselectRows(indices)
- 参数含义:
indices是当前页内需要取消选择的行索引数组 - 行为:只移除指定项,不影响其它已选行
selectAll()
- 含义:选中当前分页切片中的全部行
- 注意:不是全量数据全选
deselectAll()
- 含义:清空当前组件维护的行选中状态
getSelectedRowIndices()
- 返回值含义:返回当前页中已选行索引,结果会按从小到大排序
getSelection()
- 返回值含义:返回当前单元格框选范围
- 结果解释:若返回
null,表示当前没有有效选区
clearSelection()
- 含义:清空当前单元格选区,不影响行选择状态
getSortState() / setSortState(state)
getSortState():获取当前排序列和排序方向setSortState(state):直接改排序状态并重绘state.key:排序列 keystate.order:'asc'、'desc'或null- 注意:这里是直接设置内部排序状态,适合做外部排序同步
getScrollLeft() / getScrollTop()
- 返回值含义:当前实际滚动位置,单位是像素
toggleExpand(rowKey)
- 参数含义:
rowKey是树节点业务主键,对应treeProps.rowKey指定的字段值 - 行为:已展开则折叠,未展开则展开
- 懒加载场景:首次展开时可能触发
loadChildren
expandAll() / collapseAll()
- 含义:一次性展开或折叠全部树节点
- 注意:只对树形模式有效
getExpandedKeys()
- 返回值含义:返回当前所有已展开节点的 rowKey 数组
goTo(page)
- 参数含义:目标页码,从
1开始 - 行为:内部会自动限制在合法页码范围内
prevPage() / nextPage()
- 含义:翻到上一页或下一页
- 行为:到达边界时不会继续超出
setPageSize(size)
- 参数含义:新的每页条数
- 行为:更新后会把当前页重置到第
1页
getCurrentPage() / getPageCount() / getTotal()
getCurrentPage():当前页码getPageCount():按total / pageSize计算出的总页数getTotal():当前总条数,优先取pagination.total
核心类型说明
类型定义位于 components/pro-table/types.ts。
RowMeta / RowData
interface RowMeta {
__checkable__?: boolean
__resizable__?: boolean
__minHeight__?: number
__maxHeight__?: number
__level__?: number
__expanded__?: boolean
__hasChildren__?: boolean
__isLeaf__?: boolean
__loading__?: boolean
}
type RowData = RowMeta & Record<string, any>
| 字段 | 类型 | 说明 |
|---|---|---|
| checkable | boolean |
类型中定义为“是否允许勾选”。但当前源码未在行选择逻辑中消费该字段,如需禁选需自行扩展 |
| resizable | boolean |
设为 true 后,该行底边会出现行高拖拽手柄 |
| minHeight | number |
行高拖拽最小值,默认 20 |
| maxHeight | number |
行高拖拽最大值,默认 4000 |
| level | number |
树形模式下自动注入的层级 |
| expanded | boolean |
树形模式下自动注入的展开状态 |
| hasChildren | boolean |
树形模式下自动注入,表示是否有子节点 |
| isLeaf | boolean |
树形模式下自动注入,表示是否叶子节点 |
| loading | boolean |
懒加载树形节点时的加载中状态 |
CellSpan
interface CellSpan {
colspan?: number
rowspan?: number
}
用于描述单元格合并:
colspan表示向右合并几列rowspan表示向下合并几行- 列合并不能跨固定区,
fixedLeft、主区、fixedRight各自独立
ColumnNode
interface ColumnNode {
key: string
title: string
width?: number
minWidth?: number
maxWidth?: number
resizable?: boolean
headerAlign?: 'left' | 'center' | 'right'
cellAlign?: 'left' | 'center' | 'right'
fixed?: 'left' | 'right'
cellBgColor?: string
render?: (params: CellRenderParams) => void
children?: ColumnNode[]
sortable?: boolean
sorter?: (a: RowData, b: RowData) => number
defaultSortOrder?: 'asc' | 'desc' | null
cellOverflow?: 'clip' | 'ellipsis' | 'wrap'
maxLines?: number
tooltip?: boolean
span?: (row: RowData, rowIndex: number) => CellSpan | null | undefined
}
| 字段 | 类型 | 说明 |
|---|---|---|
| key | string |
列唯一标识,必须唯一 |
| title | string |
表头标题 |
| width | number |
列宽 |
| minWidth | number |
最小列宽,拖拽时生效,默认 30 |
| maxWidth | number |
最大列宽,拖拽时生效,默认 4000 |
| resizable | boolean |
是否允许拖拽调整列宽 |
| headerAlign | TextAlign |
表头文字对齐 |
| cellAlign | TextAlign |
单元格文字对齐 |
| fixed | 'left' \| 'right' |
固定列方向。父列设置后子列会继承 |
| cellBgColor | string |
当前列的单元格背景色 |
| render | (params: CellRenderParams) => void |
自定义单元格绘制函数。有该函数时默认文本不再绘制 |
| children | ColumnNode[] |
多级表头子列 |
| sortable | boolean |
是否支持排序 |
| sorter | (a, b) => number |
自定义排序函数 |
| defaultSortOrder | 'asc' \| 'desc' \| null |
初始排序状态 |
| cellOverflow | 'clip' \| 'ellipsis' \| 'wrap' |
文本溢出处理方式 |
| maxLines | number |
折行时最大行数,0 表示不限 |
| tooltip | boolean |
H5 悬浮或小程序点击时显示完整内容 |
| span | (row, rowIndex) => CellSpan |
body 单元格动态合并配置 |
CellRenderParams
自定义列 render 和固定行 cellRender 会收到以下参数:
interface CellRenderParams {
ctx: IRenderer
x: number
y: number
width: number
height: number
row: RowData
value: any
rowIndex: number
align: TextAlign
fontSize: number
paddingX: number
textColor: string
isHovered: boolean
hoveredLocalX: number
hoveredLocalY: number
pressedAreaKey: string | null
drawCircle(fillColor: string, text?: string, textColor?: string): void
drawText(text: string | number, color?: string): void
drawButtons(buttons: ActionButtonConfig[]): void
registerClickArea(
key: string,
x: number,
y: number,
w: number,
h: number,
onClick: (row: RowData, rowIndex: number) => void,
): void
}
几个常用能力:
drawText:按列对齐和内边距绘制文本drawCircle:绘制圆形徽标drawButtons:绘制操作按钮并自动接管点击态registerClickArea:注册当前单元格内部的局部点击区域
字段含义补充:
| 字段 | 含义 |
|---|---|
| ctx | 当前渲染器实例,可直接调用绘图 API |
| x / y | 单元格左上角坐标 |
| width / height | 单元格宽高 |
| row | 当前行数据对象 |
| value | 当前列在该行上的值 |
| rowIndex | 当前行索引 |
| align | 当前列最终文本对齐方式 |
| fontSize | 当前实际字号 |
| paddingX | 当前单元格水平内边距 |
| textColor | 当前默认文字颜色 |
| isHovered | 当前单元格所在行是否处于 hover 状态 |
| hoveredLocalX / hoveredLocalY | 指针位于单元格内部的相对坐标,未 hover 时通常为 -1 |
| pressedAreaKey | 当前被按下的内部点击区域 key,没有则为 null |
ActionButtonConfig
interface ActionButtonConfig {
key: string
label: string
type?: 'button' | 'link'
color?: string
textColor?: string
hoverColor?: string
onClick?: (row: RowData, rowIndex: number) => void
}
| 字段 | 类型 | 说明 |
|---|---|---|
| key | string |
按钮唯一标识 |
| label | string |
按钮文案 |
| type | 'button' \| 'link' |
展现样式,默认 link |
| color | string |
主色,默认 #1890ff |
| textColor | string |
按钮文字色,仅 button 模式下有效 |
| hoverColor | string |
hover 时颜色 |
| onClick | (row, rowIndex) => void |
点击回调 |
FixedRowDef
interface FixedRowDef {
position: 'top' | 'bottom'
data: RowData
cellRender?: Record<string, (params: CellRenderParams) => void>
spans?: Record<string, CellSpan>
}
| 字段 | 类型 | 说明 |
|---|---|---|
| position | 'top' \| 'bottom' |
固定行位置 |
| data | RowData |
固定行数据 |
| cellRender | Record<string, (params) => void> |
指定列 key 的固定行自定义绘制,优先级高于列级 render |
| spans | Record<string, CellSpan> |
固定行单元格合并配置 |
ProTableOptions
interface ProTableOptions {
borderColor?: string
headerBgColor?: string
bodyBgColor?: string
hoverRowBgColor?: string
hoverColBgColor?: string
stripedBgColor?: string
textColor?: string
fontSize?: number
padding?: number | [number, number]
rowBgColor?: (row: RowData, rowIndex: number) => string | undefined
cellBgColor?: (row: RowData, rowIndex: number, colKey: string) => string | undefined
selectionFillColor?: string
selectionBorderColor?: string
resizeHandleVisible?: boolean
}
实际默认值如下:
{
borderColor: '#e8e8e8',
headerBgColor: '#fafafa',
bodyBgColor: '#ffffff',
hoverRowBgColor: '#f5f5f5',
hoverColBgColor: '#f0f7ff',
stripedBgColor: '#fafafa',
textColor: '#333333',
fontSize: 13,
padding: [8, 8],
selectionFillColor: 'rgba(24,144,255,0.12)',
selectionBorderColor: '#1890ff',
resizeHandleVisible: false,
}
说明:
padding支持number或[paddingY, paddingX]- 行高会按
ceil(fontSize * 1.2) + paddingY * 2自动推导 rowBgColor是行级背景色回调cellBgColor优先级高于rowBgColor和列级cellBgColorresizeHandleVisible当前实际默认值是false
字段含义补充:
| 字段 | 含义 |
|---|---|
| borderColor | 单元格网格线颜色 |
| headerBgColor | 表头背景色 |
| bodyBgColor | 表体默认背景色 |
| hoverRowBgColor | 行 hover 时覆盖的背景色 |
| hoverColBgColor | 列 hover 时覆盖的背景色 |
| stripedBgColor | 斑马纹行背景色 |
| textColor | 默认文字颜色 |
| fontSize | 默认字号,会参与行高计算 |
| padding | 单元格内边距,控制内容与边框的距离 |
| rowBgColor | 按行动态返回背景色的回调 |
| cellBgColor | 按单元格动态返回背景色的回调 |
| selectionFillColor | 选区内部填充色 |
| selectionBorderColor | 选区边框颜色 |
| resizeHandleVisible | 是否绘制列宽/行高拖拽手柄指示条 |
RowSelectionConfig
interface RowSelectionConfig {
type?: 'checkbox' | 'radio'
columnTitle?: string
columnWidth?: number | string
fixed?: boolean
hideSelectAll?: boolean
}
| 字段 | 类型 | 说明 |
|---|---|---|
| type | 'checkbox' \| 'radio' |
选择模式,默认 checkbox |
| columnTitle | string |
选择列表头标题。设置后表头不再绘制默认全选框 |
| columnWidth | number \| string |
选择列宽,默认 40。传字符串时会用 parseInt 解析 |
| fixed | boolean |
是否固定到左侧,默认 true |
| hideSelectAll | boolean |
隐藏表头全选框,仅 checkbox 模式且未设置 columnTitle 时有效 |
注意事项:
selectedRowKeys与row-select-change.indices使用的是当前分页切片内的索引,不是业务主键selectAll()也只作用于当前页数据
SelectionRange
interface SelectionRange {
startRow: number
endRow: number
startColIndex: number
endColIndex: number
}
SelectionRange 中的行索引是统一虚拟行索引:
- 负值:固定顶部行
0 ~ data.length - 1:body 行- 大于等于
data.length:固定底部行
列索引对应 layout.leafColumns 顺序,也就是“固定左列 -> 主区列 -> 固定右列”。
字段含义补充:
| 字段 | 含义 |
|---|---|
| startRow | 选区起始行 |
| endRow | 选区结束行 |
| startColIndex | 选区起始列索引 |
| endColIndex | 选区结束列索引 |
说明:起止值不要求一定是左上到右下,消费时建议自己做一次 min/max 归一化。
SortState
type SortOrder = 'asc' | 'desc' | null
interface SortState {
key: string
order: SortOrder
}
| 字段 | 类型 | 说明 |
|---|---|---|
| key | string |
当前排序列 key |
| order | 'asc' \| 'desc' \| null |
排序方向 |
TreeConfig
interface TreeConfig {
childrenKey?: string
indent?: number
defaultExpandAll?: boolean
defaultExpandedKeys?: Array<string | number>
rowKey?: string
treeColumnKey?: string
lazy?: boolean
loadChildren?: (row: RowData) => Promise<RowData[]>
hasChildrenField?: string
}
| 字段 | 类型 | 说明 |
|---|---|---|
| childrenKey | string |
子节点字段名,默认 children |
| indent | number |
每级缩进像素,默认 8 |
| defaultExpandAll | boolean |
初始是否展开全部 |
| defaultExpandedKeys | Array<string \| number> |
初始展开的 rowKey 列表 |
| rowKey | string |
行唯一键字段,默认 id |
| treeColumnKey | string |
显示树形缩进和展开图标的列 key,默认第一列叶子列 |
| lazy | boolean |
是否启用懒加载树 |
| loadChildren | (row) => Promise<RowData[]> |
懒加载时首次展开节点所调用的异步方法 |
| hasChildrenField | string |
标识可展开节点的字段名,默认 hasChildren |
行为说明:
- 懒加载模式下,首次展开某个节点时会调用
loadChildren - 加载过程中会给该行注入
__loading__ = true toggleExpand(rowKey)传的是 rowKey 值,不是行索引
PaginationConfig
interface PaginationConfig {
current: number
pageSize: number
total: number
pageSizeOptions?: number[]
}
| 字段 | 类型 | 说明 |
|---|---|---|
| current | number |
当前页码,从 1 开始 |
| pageSize | number |
每页条数 |
| total | number |
总条数。服务端分页时可传后端总数 |
| pageSizeOptions | number[] |
每页条数备选值,仅作为配置数据保存,组件本身不渲染分页器 |
行为说明:
- 不传
pagination时,组件直接使用全量数据 - 传入
pagination时,组件对当前数据执行切片 - 组件提供分页方法和
page-change事件,但不提供内置分页栏 UI
OverlayDrawPayload
bodyOverlayDraw、fixedTopOverlayDraw、fixedBottomOverlayDraw 会收到以下 payload:
interface OverlayDrawPayload {
renderer: IRenderer
helper: any
getColIndexByKey(key: string): number
getCellCenter(colIndex: number, rowIndex: number): { x: number; y: number }
getCellRadius(colIndex: number): number
drawCircle(x: number, y: number, r: number, color: string, text?: string, textColor?: string): void
drawPolyline(points: Array<{ x: number; y: number }>, color: string, lineWidth?: number): void
drawCellBg(colIndex: number, rowIndex: number, color: string): void
drawText(
text: string,
x: number,
y: number,
opts?: {
color?: string
fontSize?: number
align?: 'left' | 'center' | 'right'
baseline?: 'top' | 'middle' | 'bottom'
},
): void
}
这个 payload 适合做趋势线、角标、额外装饰、热力区块等高阶绘制。
字段含义补充:
| 字段 | 含义 |
|---|---|
| renderer | 底层渲染器实例,适合做更底层的自定义绘图 |
| helper | 内部坐标辅助对象,封装了单元格定位和常用绘制能力 |
| getColIndexByKey | 根据列 key 找到叶子列索引 |
| getCellCenter | 获取某个单元格中心点坐标 |
| getCellRadius | 获取某列单元格适合绘圆点时的推荐半径 |
| drawCircle | 在指定位置绘制一个圆,可附带居中文字 |
| drawPolyline | 根据点集绘制折线 |
| drawCellBg | 给指定单元格补一层背景色 |
| drawText | 在任意坐标绘制文字,可指定颜色、字号、对齐和基线 |
常见用法
1. 行选择
<pro-table
v-model:selectedRowKeys="selectedRowKeys"
:columns="columns"
:data="data"
:row-selection="{ type: 'checkbox', columnWidth: 48 }"
@row-select-change="onRowSelectChange"
/>
const selectedRowKeys = ref<number[]>([])
function onRowSelectChange(payload: { indices: number[]; rows: RowData[] }) {
console.log(payload.indices, payload.rows)
}
2. 树形表格
<pro-table
:columns="columns"
:data="treeData"
:tree-props="{
rowKey: 'id',
childrenKey: 'children',
treeColumnKey: 'name',
indent: 12,
defaultExpandAll: true,
}"
/>
3. 固定行
const fixedRows: FixedRowDef[] = [
{
position: 'top',
data: { name: '顶部汇总', salary: 300000 },
},
{
position: 'bottom',
data: { name: '底部合计', salary: 280000 },
spans: {
name: { colspan: 2 },
},
},
]
4. 自定义单元格绘制
const columns: ColumnNode[] = [
{
key: 'progress',
title: '进度',
width: 120,
render: ({ ctx, x, y, width, height, value, drawText }) => {
const percent = Number(value) || 0
ctx.setFillStyle('#f0f0f0')
ctx.fillRect(x + 8, y + height / 2 - 4, width - 16, 8)
ctx.setFillStyle('#1890ff')
ctx.fillRect(x + 8, y + height / 2 - 4, ((width - 16) * percent) / 100, 8)
drawText(`${percent}%`)
},
},
]
使用注意事项
1. data 变更建议替换引用
组件对 data 使用的是引用级 watch,而不是深度 watch。这样做是为了避免大数组深遍历的性能开销。
推荐:
data.value = [...data.value, newRow]
不推荐依赖深层属性原地修改后自动触发布局重算。
2. 行选择索引是“当前页索引”
无论是 selectedRowKeys、row-select-change.indices、getSelectedRowIndices(),当前实现返回的都是分页切片内索引,而不是业务主键。
如果你的业务需要稳定主键选择,建议在外层把索引映射成真实 id 存储。
3. 分页是逻辑分页,不是完整分页组件
pagination 只负责:
- 当前页切片
- 页码状态
- 对外暴露翻页方法
- 触发
page-change
它不负责渲染页码器、页大小切换器、总数展示。
4. resizeHandleVisible 当前默认是 false
源码合并默认值时,resizeHandleVisible 的实际默认行为是 false。如果你希望显示列宽 / 行高拖拽手柄,需要显式设置:
const options: ProTableOptions = {
resizeHandleVisible: true,
}
建议的类型导入方式
import type {
RowData,
ColumnNode,
ProTableOptions,
FixedRowDef,
RowSelectionConfig,
SelectionRange,
SortState,
TreeConfig,
PaginationConfig,
CellRenderParams,
ActionButtonConfig,
OverlayDrawPayload,
} from '@/uni_modules/pro-table'

收藏人数:
购买普通授权版(
试用
使用 HBuilderX 导入示例项目
赞赏(0)
下载 93
赞赏 0
下载 11623061
赞赏 1906
赞赏
京公网安备:11010802035340号