更新记录
1.3.3(2026-07-03)
基础表格、多表头、多选、树形表格、异步加载、排序、操作按钮、列宽拖拽、固定列、上拉加载、分页、插槽、自定义样式、图片列等
平台兼容性
uni-app(4.0)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | - | - | - | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | - | - | - | - | - | - | - | - | - | - | - |
其他
| 多语言 | 暗黑模式 | 宽屏模式 |
|---|---|---|
| × | × | √ |
介绍
基于 uni-app 开发的多功能表格组件,支持固定表头/首列/多列(含右固定)、排序(内置 & 自定义)、操作按钮、上拉加载更多、懒加载状态机、自适应列宽、列宽拖拽调整、多选 checkbox、图片展示与预览、单元格提示浮层、合计行、树形表格(同步/异步懒加载)、多级表头、分页、插槽自定义列渲染、H5 自定义横向滚动条等。已用于生产环境。
兼容多端:H5、App-Vue、微信/阿里/百度/字节/QQ 小程序、快应用(华为/联盟)。
本组件基于 zb-table 进行二次开发,在原版基础上新增了工具栏(列设置面板)、懒加载状态机、右固定列、列宽拖拽调整、树形表格(同步/异步懒加载/按层级展开)、自定义横向滚动条、单选模式、禁止复制、自定义行样式、隐藏列等功能,并修复了列宽对齐、拖拽宽度保留等多项问题。
原项目地址:https://github.com/zouzhibin/zb-table | 原作者:zouzhibin
目录
快速使用
在 uni_modules 目录下直接引入即可自动注册组件:
<zb-table :columns="columns" :data="data"></zb-table>
export default {
data() {
return {
columns: [
{ type: 'selection', fixed: true, width: 50 },
{ name: 'name', label: '姓名', width: 80, emptyString: '--' },
{ name: 'age', label: '年纪', sorter: false, align: 'right' },
{ name: 'sex', label: '性别', filters: { 0: '男', 1: '女' } }, // 也支持数组: [{value:0, label:'男'},{value:1, label:'女'}]
{ name: 'img', label: '图片', type: 'img' },
{ name: 'address', label: '地址' },
{ name: 'date', label: '日期', sorter: true },
{ name: 'province', label: '省份' },
{ name: 'city', label: '城市' },
{ name: 'zip', label: '邮编' },
{ name: 'operation', type: 'operation', label: '操作', renders: [
{ name: '编辑', func: 'edit' },
{ name: '删除', type: 'warn', func: 'dele' }
]}
],
data: [
{ date: '2016-05-02', name: '王小虎1', province: '上海', sex: 0, age: 18,
img: 'https://img1.baidu.com/it/u=300787145,1214060415&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500',
city: '普陀区', address: '上海市普', zip: 200333 },
{ date: '2016-05-02', name: '王小虎2', province: '上海', sex: 0, age: 18,
city: '普陀区', address: '上海市普', zip: 200333 },
{ date: '2016-05-02', name: '王小虎3', province: '上海', sex: 1, age: 20,
city: '普陀区', address: '上海市普', zip: 200333 }
]
}
}
}
Table 属性
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 是否必须 |
|---|---|---|---|---|---|
| data | 显示的数据 | Array | — | [] |
必须 |
| columns | 列配置数组,详见 Column 属性 | Array | — | [] |
必须 |
| stripe | 是否显示斑马纹 | Boolean | true / false | true |
否 |
| fit | 列宽是否自撑开(自适应内容宽度) | Boolean | true / false | false |
否 |
| showHeader | 是否显示表头 | Boolean | true / false | true |
否 |
| border | 是否带有纵向边框 | Boolean | true / false | false |
否 |
| highlight | 是否高亮当前行 | Boolean | true / false | false |
否 |
| itemDate | 高亮行匹配对象(配合 highlight 使用,通过 rowKey 匹配) | Object | — | {} |
否 |
| rowKey | 行唯一键,用于行选择/树形表格等场景。可为 String(字段名)或 Function(返回唯一值) | String / Function | — | — | 否 |
| showSummary | 是否在表尾显示合计行 | Boolean | true / false | false |
否 |
| sumText | 合计行第一列的文本 | String | — | '合计' |
否 |
| summaryMethod | 自定义合计计算方法 | Function({ columns, data }) | — | — | 否 |
| cellStyle | 单元格样式回调方法,也可用固定 Object | Function({row, column, rowIndex, columnIndex}) / Object | — | — | 否 |
| cellHeaderStyle | 表头单元格样式回调方法,也可用固定 Object | Function({column, columnIndex}) / Object | — | — | 否 |
| rowStyle | 行样式回调方法,也可用固定 Object | Function({row, rowIndex}) / Object | — | — | 否 |
| formatter | 全局数据格式化函数(需 column 的 formatter 为 true 才生效),返回格式化后的字符串 | Function(row, column, rowIndex, columnIndex): string | — | — | 否 |
| permissionBtn | 动态控制操作按钮的显示隐藏,返回过滤后的 renders 数组 | Function(row, renders, index): Array | — | — | 否 |
| headerRowHeight | 表头行高 (px) | Number | — | 40 |
否 |
| rowHeight | 数据行高 (px) | Number | — | 40 |
否 |
| height | 表格高度 (px),大于0时启用固定高度+内部滚动,为0时自适应内容高度 | Number | — | 0 |
否 |
| cellPadding | 单元格内边距,如 "0px 8px 0rpx 8px" |
String | — | "0px 8px 0rpx 8px" |
否 |
上拉加载(传统模式)
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 是否必须 |
|---|---|---|---|---|---|
| isShowLoadMore | 是否开启上拉加载 | Boolean | true / false | false |
否 |
| pullUpLoading | 上拉加载回调函数,参数 done 为函数,done() 代表还有数据继续加载,done('ok') 代表结束 |
Function(done) | — | — | 否 |
关闭上拉加载方式 1(回调内):
pullUpLoading((done) => {
// 请求数据...
done() // 还有数据,继续开启上拉加载
done('ok') // 无数据,结束上拉加载
})
关闭上拉加载方式 2(手动调用):
this.$refs.zbTable.pullUpCompleteLoading('ok')
懒加载状态机(推荐替代传统上拉加载)
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 是否必须 |
|---|---|---|---|---|---|
| lazyLoad | 是否启用懒加载状态机(idle/loading/noMore/error) | Boolean | true / false | false |
否 |
| lazyLoadText | 各状态文字配置 | Object | — | { loading: '加载中...', noMore: '没有更多了', error: '加载失败,点击重试' } |
否 |
| lazyLoadThreshold | 懒加载触发阈值 (px),距底部多少 px 时触发加载 | Number | — | 40 |
否 |
分页
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 是否必须 |
|---|---|---|---|---|---|
| pagination | 是否启用分页模式 | Boolean | true / false | false |
否 |
| currentPage | 当前页码(支持 .sync 双向绑定) |
Number | — | 1 |
否 |
| pageSize | 每页条数 | Number | — | 10 |
否 |
| total | 总数据条数 | Number | — | 0 |
否 |
| pageSizeOptions | 每页条数选项数组 | Array | — | [10, 20, 50, 100] |
否 |
| showPageSizeChanger | 是否显示每页条数切换器 | Boolean | true / false | false |
否 |
| showQuickJumper | 是否显示快速跳转输入框 | Boolean | true / false | false |
否 |
树形表格
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 是否必须 |
|---|---|---|---|---|---|
| treeProps | 树形配置:{ children: 'children字段名', hasChildren: 'hasChildren字段名' } |
Object | — | { children: 'children', hasChildren: 'hasChildren' } |
否 |
| treeColumnName | 树节点展示的列 name,不指定则取第一个非 selection/index 列 | String | — | '' |
否 |
| defaultExpandAll | 是否默认展开所有树节点 | Boolean | true / false | false |
否 |
| defaultExpandLevel | 默认展开树节点的层数(1=只展开第一层,2=展开前两层,依此类推;0或未设置则不展开) | Number | — | 0 |
否 |
| indent | 每级缩进距离 (px) | Number | — | 16 |
否 |
| treeLoad | 异步加载子节点函数,调用 resolve(childrenArray) 完成加载 |
Function(row, resolve) | — | — | 否 |
注意:树形异步懒加载时,只有数据项显式包含
hasChildren: true才会显示展开箭头并触发treeLoad,否则视为叶子节点。
列宽拖拽调整
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 是否必须 |
|---|---|---|---|---|---|
| resizable | 是否启用列宽拖拽调整 | Boolean | true / false | false |
否 |
| resizeMinWidth | 拖拽调整时的最小列宽 (px) | Number | — | 40 |
否 |
横向滚动条(H5 PC端)
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 是否必须 |
|---|---|---|---|---|---|
| showHScrollbar | 自定义横向滚动条显示策略 | Boolean / String | true=始终显示, false=始终隐藏, "auto"=窗口宽度>720px时显示 |
"auto" |
否 |
说明:H5 端在表格底部提供了自定义横向滚动条,支持鼠标拖拽滑块和点击轨道跳转,移动端支持触摸拖动。
showHScrollbar默认"auto"模式下,PC 端(窗口宽度 > 720px)自动显示滚动条,移动端自动隐藏,使用原生滑动。
工具栏(列设置面板)
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 是否必须 |
|---|---|---|---|---|---|
| toolbar | 是否显示工具栏(列设置按钮,支持列显隐、对齐、固定、拖拽排序等) | Boolean | true / false | false |
否 |
| singleSelect | 是否单选模式(true 时 selection 列显示为单选框,只能选中一行) | Boolean | true / false | false |
否 |
| disableCopy | 是否禁止表格内容复制(true 时表格内容不可选中复制) | Boolean | true / false | false |
否 |
说明:开启
toolbar后,表格顶部会显示工具栏区域,右侧有列设置按钮,点击打开列设置面板。面板中用户可以:
- 勾选/取消勾选列名来控制列显隐
- 点击对齐按钮设置左对齐/居中/右对齐
- 点击固定按钮设置左固定/右固定/取消固定
- 拖拽或点击上下移按钮调整列顺序
selection和index类型列不在面板中显示- 可通过
#toolbar插槽在工具栏左侧放置自定义内容
Table 事件
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| 自定义事件名 | 操作按钮点击事件,取决于 column renders 中 func 的参数名 |
(row, index) |
| sort-change | 自定义排序时触发(column.sorter='custom') | (column, 'asc'/'desc', columnIndex) |
| currentChange | 当前行变化时触发,需开启 highlight |
(row, index) |
| toggleAllSelection | 全选复选框变化 | (selected, selectedArray) |
| toggleRowSelection | 单行复选框变化 | (selected, selectedArray) |
| getSelection | 调用 getSelection() 方法时触发,返回当前选中行数组 |
(selectedArray) |
| rowClick | 单击某行 | (row, index) |
| cellClick | 单击单元格 | (row, index, column) |
| pullUpLoading | 上拉加载触发(传统模式) | 无参数 |
| expand-change | 树节点展开/折叠时触发 | (row, expanded) |
| update:currentPage | 分页当前页同步事件(支持 .sync 修饰符) |
page 值 |
| pageChange | 分页页码变化时触发 | { currentPage, pageSize } |
| pageSizeChange | 分页每页条数变化时触发 | { currentPage, pageSize } |
| column-change | 工具栏中列配置变化时触发(显隐/对齐/固定/排序) | { type: 'visible'|'align'|'fixed'|'order', column, value } |
Table 方法(通过 ref 调用)
| 方法名 | 说明 | 参数 |
|---|---|---|
| pullUpCompleteLoading | 结束上拉加载状态 | type:空字符串代表还有数据,'ok' 代表结束 |
| setLazyLoadStatus | 手动设置懒加载状态 | status:'idle' / 'loading' / 'noMore' / 'error' |
| retryLazyLoad | 懒加载错误时点击重试 | 无 |
| resetHighlight | 清除高亮行选中状态 | 无 |
| clearSelection | 清除所有复选框选中 | 无 |
| getSelection | 获取当前选中的行数据数组,同时触发 getSelection 事件 |
无 |
| changePage | 切换到指定页(分页模式) | page:页码 |
| onPageSizeChange | 切换每页条数(分页模式) | size:每页条数 |
| toggleToolbarPanel | 切换工具栏列设置面板显隐 | 无 |
| closeToolbarPanel | 关闭工具栏列设置面板 | 无 |
| toggleColumnVisible | 切换列的显隐状态 | col:叶子列配置对象 |
| setColumnAlign | 设置列对齐方式 | col:列配置对象, align:'left'/'center'/'right' |
| setColumnFixed | 设置列固定方式 | col:列配置对象, fixed:true/'left'/'right'/false |
| moveColumnUp | 上移列顺序 | idx:列在面板中的索引 |
| moveColumnDown | 下移列顺序 | idx:列在面板中的索引 |
| toggleRowExpansion | 切换树节点展开/折叠状态 | row:行数据对象 |
Data 属性
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| checked | 是否被勾选(多选模式下初始选中) | Boolean | true / false | 无 |
| key | 行唯一标识(组件内部自动生成,设置 rowKey 后基于 rowKey 字段值生成,否则使用数组索引) | String / Number | — | 自动生成 |
树形数据额外属性
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| children | 子节点数组(同步树形表格) | Array | — | — |
| hasChildren | 是否有子节点(异步懒加载,设为 true 才显示展开箭头) |
Boolean | true / false | — |
Column 属性
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| name | 数据字段名 | String | — | — |
| label | 列标题文本 | String | — | — |
| width | 列宽度 (px),未设置时默认 100,列宽不足容器宽度时自动分配剩余空间 | Number | — | 100 |
| minWidth | 列最小宽度 (px),列宽计算结果低于此值时自动修正为 minWidth | Number | — | — |
| type | 列类型 | String | selection / index / operation / img / slot |
普通文本列 |
| align | 对齐方式 | String | left / center / right |
left |
| fixed | 固定列 | Boolean / String | true 或 'left' 为左固定,'right' 为右固定 |
— |
| sorter | 排序 | Boolean / String | true(内置排序)/ 'custom'(自定义排序,触发 sort-change 事件) |
false |
| filters | 值映射过滤器,对象格式 {1:'启用', 0:'停用'} 或数组格式 [{value:1, label:'启用'}, {value:0, label:'停用'}] |
Object / Array | — | — |
| emptyString | 空值时显示的占位文本 | String | — | '--' |
| formatter | 标记此列使用全局 formatter 函数格式化 | Any | — | — |
| slot | 插槽名称,用于自定义列渲染内容(微信小程序需同时设置 tableCell) |
String | — | — |
| headerSlot | 自定义表头插槽名称(可选,不设置则与 slot 同名) | String | — | — |
| showtips | 是否启用长按/双击显示完整内容提示浮层 | Boolean | true / false | false |
| tipsTime | showtips 提示浮层显示时长 (ms) | Number | — | 3000 |
| renders | 操作按钮配置(仅 type='operation') | Array | — | — |
| children | 子列配置(多级表头),格式同 columns | Array | — | — |
| tableCell | 微信小程序插槽名(替代 slot,因小程序不支持动态具名插槽,需与 slot 同时设置) | String | — | — |
| hidden | 是否隐藏该列(true 时该列不显示,可通过工具栏重新显示) | Boolean | true / false | false |
renders 配置项(type='operation' 时)
renders: [
{
name: '编辑', // 按钮文字
type: 'primary', // 按钮类型:primary/warn/default/custom(custom 为纯文字链接样式)
size: 'mini', // 按钮大小:mini/medium/default
func: 'edit', // 点击事件名,父组件通过 @edit 接收
class: '' // 自定义 CSS class
},
{
name: '删除',
type: 'warn',
func: 'dele'
}
]
父组件接收事件:<zb-table @edit="onEdit" @dele="onDele" />
<!-- end Column 属性 -->
插槽
该组件采用动态插槽模式,插槽名称由 column.slot 属性指定,无需在组件上预先声明具名插槽。
注意:微信小程序不支持动态具名插槽,需在使用
slot的同时设置column.tableCell属性作为小程序插槽名。其他平台仅需slot即可。
| 插槽名 | 说明 | 作用域变量 |
|---|---|---|
[动态,由 column.slot 指定] |
自定义列内容渲染(表体) | { row, column, index } |
[由 column.headerSlot 或 column.slot 指定] |
自定义表头列渲染(表头),需设置 headerSlot |
{ row: column, column: column, index } |
toolbar |
工具栏左侧自定义内容(需开启 toolbar 属性) |
无 |
作用域变量说明
| 变量 | 说明 |
|---|---|
row |
当前行数据对象(表头插槽中为列配置对象) |
column |
当前列配置对象 |
index |
行索引,从 0 开始(表头插槽中为 column.leafStartIndex) |
表头列插槽
当 column.slot 有值时,表体列和表头列均可使用同名插槽进行自定义渲染。如需表头与表体使用不同插槽名,可通过 column.headerSlot 单独指定表头插槽名(未设置时默认与 slot 同名)。表头插槽作用域中 row 指向列配置对象,index 指向列的叶子起始索引。
示例:
<zb-table :columns="columns" :data="data">
<!-- 表体插槽,自定义列内容 -->
<template #statusSlot="{ row, column, index }">
<text :style="{ color: row.status === 1 ? 'green' : 'red' }">
{{ row.status === 1 ? '在线' : '离线' }}
</text>
</template>
<!-- 表头插槽,通过 headerSlot 指定不同插槽名 -->
<template #statusHeader="{ row: column }">
<view class="custom-header">{{ column.label }}<text class="badge">NEW</text></view>
</template>
</zb-table>
columns: [
{ name: 'status', label: '状态', slot: 'statusSlot', headerSlot: 'statusHeader' }
]
注意:如果仅需要自定义表体列内容,直接使用
column.slot指定插槽名即可。表头插槽为可选扩展,仅在需要自定义表头时使用。
<!-- end 插槽 -->
使用示例
基础表格
<zb-table
:columns="columns"
:data="data"
:stripe="true"
:border="true"
:fit="false"
show-summary
sum-text="合计"
:summary-method="getSummaries"
@toggleRowSelection="toggleRowSelection"
@toggleAllSelection="toggleAllSelection"
@rowClick="rowClick"
@edit="buttonEdit"
@dele="dele"
></zb-table>
树形表格(同步数据)
<zb-table
ref="zbTable"
:columns="treeColumns"
:data="treeData"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
tree-column-name="name"
:default-expand-all="false"
:indent="20"
row-key="id"
@expand-change="onExpandChange"
></zb-table>
treeColumns: [
{ name: 'name', label: '名称' }, // treeColumnName='name' 指定此列展示树形缩进和展开图标
{ name: 'count', label: '人数', width: 80 },
{ name: 'operation', type: 'operation', label: '操作', width: 150, renders: [
{ name: '编辑', func: 'edit' }
]}
],
treeData: [
{ id: 1, name: '部门A', count: 20, children: [
{ id: 11, name: '小组1', count: 8 },
{ id: 12, name: '小组2', count: 12 }
]}
],
methods: {
onExpandChange(row, expanded) {
console.log(row.name, expanded ? '展开' : '折叠')
},
// 手动切换某行的展开/折叠
toggleNode(row) {
this.$refs.zbTable.toggleRowExpansion(row)
}
}
说明:
treeColumnName指定树形缩进和展开图标显示在哪一列。不设置时默认取第一个非selection/index类型的列。
树形表格(按层级展开)
使用 defaultExpandLevel 控制初始展开的层级数,比 defaultExpandAll 更灵活。
<zb-table
:columns="treeColumns"
:data="treeData"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
:default-expand-level="1"
:indent="20"
row-key="id"
></zb-table>
// defaultExpandLevel=1:只展开根节点(第一层),子节点默认折叠
// defaultExpandLevel=2:展开前两层,依此类推
// defaultExpandLevel=0:不展开任何节点(默认行为)
treeData: [
{ id: 1, name: '总部', children: [
{ id: 11, name: '部门A', children: [
{ id: 111, name: '小组1' },
{ id: 112, name: '小组2' }
]},
{ id: 12, name: '部门B', children: [
{ id: 121, name: '小组3' }
]}
]}
]
说明:
defaultExpandAll和defaultExpandLevel同时存在时,defaultExpandAll优先。两者仅对同步数据有效,异步懒加载需通过treeLoad动态加载后展开。
树形表格(异步懒加载)
<zb-table
:columns="treeColumns"
:data="treeData"
:tree-props="{ hasChildren: 'hasChildren' }"
:tree-load="loadTreeChildren"
row-key="id"
></zb-table>
// 只有 hasChildren: true 的行才显示展开箭头并触发懒加载
treeData: [
{ id: 1, name: '部门A', hasChildren: true } // 显示展开箭头
{ id: 2, name: '部门B' } // 叶子节点,无箭头
],
methods: {
loadTreeChildren(row, resolve) {
// 异步请求子节点数据
setTimeout(() => {
resolve([
{ id: row.id * 10 + 1, name: '子节点1' },
{ id: row.id * 10 + 2, name: '子节点2' }
])
}, 500)
}
}
分页模式
<zb-table
:columns="columns"
:data="data"
:pagination="true"
:current-page.sync="currentPage"
:page-size="pageSize"
:total="total"
:show-page-size-changer="true"
:show-quick-jumper="true"
@pageChange="onPageChange"
@pageSizeChange="onPageSizeChange"
></zb-table>
懒加载状态机
<zb-table
:columns="columns"
:data="data"
:lazy-load="true"
:lazy-load-text="{ loading: '加载中...', noMore: '没有更多了', error: '加载失败,点击重试' }"
:lazy-load-threshold="40"
@pullUpLoading="onLoadMore"
></zb-table>
插槽自定义列
<zb-table :columns="columns" :data="data">
<template #statusSlot="{ row, column, index }">
<text :style="{ color: row.status === 1 ? 'green' : 'red' }">
{{ row.status === 1 ? '在线' : '离线' }}
</text>
</template>
</zb-table>
columns: [
{ name: 'status', label: '状态', slot: 'statusSlot' }
]
列宽拖拽调整
<zb-table
:columns="columns"
:data="data"
:resizable="true"
:resize-min-width="50"
></zb-table>
单元格提示浮层
columns: [
{ name: 'description', label: '描述', width: 120, showtips: true, tipsTime: 3000 }
]
长按或双击该列单元格时,会在触摸位置弹出完整内容提示浮层,自动消失。
H5 横向滚动条
H5 端在表格底部提供自定义横向滚动条,支持鼠标拖拽滑块、点击轨道跳转,移动端支持触摸拖动。默认 "auto" 模式:PC 端(窗口宽度 > 720px)显示,移动端自动隐藏使用原生滑动。
<!-- 默认自动模式:PC端显示,移动端隐藏 -->
<zb-table :columns="columns" :data="data"></zb-table>
<!-- 移动端也强制显示 -->
<zb-table :columns="columns" :data="data" :show-h-scrollbar="true"></zb-table>
<!-- 始终隐藏 -->
<zb-table :columns="columns" :data="data" :show-h-scrollbar="false"></zb-table>
交互说明:滑块宽度反映内容与可视区域的比例。拖拽滑块或点击轨道,表头、表体、合计行同步横向滚动,左/右固定列不受影响。
多级表头
通过 column 的 children 属性配置嵌套列,实现多级表头。子列会继承父列的 fixed 和 align 属性(子列未设置时)。
columns: [
{ name: 'name', label: '姓名', width: 80 },
{
label: '基本信息',
children: [
{ name: 'age', label: '年龄', width: 80, align: 'center' },
{ name: 'sex', label: '性别', width: 80, filters: { 0: '男', 1: '女' } }
]
},
{
label: '地址信息',
children: [
{ name: 'province', label: '省份', width: 100 },
{ name: 'city', label: '城市', width: 100 },
{ name: 'address', label: '详细地址', width: 200 }
]
},
{ name: 'operation', type: 'operation', label: '操作', width: 150, renders: [
{ name: '编辑', func: 'edit' },
{ name: '删除', type: 'warn', func: 'dele' }
]}
]
说明:多级表头中,只有叶子列(最底层的列)会渲染数据单元格,父列只渲染表头合并单元格。表头行高 = 表头行数 ×
headerRowHeight。
右固定列
通过设置 fixed: 'right' 实现右侧固定列,常用于操作按钮列。
columns: [
{ name: 'name', label: '姓名', width: 80 },
{ name: 'age', label: '年龄', width: 80 },
{ name: 'address', label: '地址' },
{ name: 'date', label: '日期', width: 120 },
// 右固定操作列
{ name: 'operation', type: 'operation', label: '操作', fixed: 'right', width: 150, renders: [
{ name: '编辑', func: 'edit' },
{ name: '删除', type: 'warn', func: 'dele' }
]}
]
说明:右固定列仅在内容宽度超出容器时才会显示为固定面板,内容未超出时与普通列一致,避免重复显示。左固定列同理。
序号列
设置 type: 'index' 即可自动显示从 1 开始的行号。
columns: [
{ type: 'index', label: '序号', width: 60, align: 'center' },
{ name: 'name', label: '姓名', width: 80 },
{ name: 'age', label: '年龄', width: 80 }
]
图片列
设置 type: 'img' 显示图片,支持单张(字符串)和多张(数组),点击可预览大图。
columns: [
{ name: 'avatar', label: '头像', type: 'img', width: 80 },
{ name: 'photos', label: '相册', type: 'img', width: 160 }
]
// 数据格式
data: [
{ avatar: 'https://example.com/img1.jpg', photos: ['https://example.com/p1.jpg', 'https://example.com/p2.jpg'] },
{ avatar: '', photos: '' } // 空值显示 emptyString
]
全局格式化(formatter)
通过 formatter prop 定义全局格式化函数,在列配置中设置 formatter: true 启用。
<zb-table
:columns="columns"
:data="data"
:formatter="globalFormatter"
></zb-table>
columns: [
{ name: 'name', label: '姓名' },
{ name: 'salary', label: '薪资', formatter: true }, // 启用全局格式化
{ name: 'date', label: '日期' }
],
methods: {
globalFormatter(row, column, rowIndex, columnIndex) {
if (column.name === 'salary') {
return '¥' + Number(row.salary).toLocaleString()
}
return row[column.name]
}
}
值映射过滤器(filters)
使用 filters 将数据值映射为显示文本,无需手动转换数据。
// 对象格式:键为数据值,值为显示文本
{ name: 'status', label: '状态', filters: { 0: '停用', 1: '启用' } }
// 数组格式:适用于键为非字符串类型
{ name: 'type', label: '类型', filters: [
{ value: 1, label: '类型A' },
{ value: 2, label: '类型B' },
{ value: 3, label: '类型C' }
]}
自定义单元格样式
通过 cellStyle 和 cellHeaderStyle 动态设置单元格样式。
<zb-table
:columns="columns"
:data="data"
:cell-style="cellStyle"
:cell-header-style="headerStyle"
></zb-table>
methods: {
// 数据行单元格样式
cellStyle({ row, column, rowIndex, columnIndex }) {
if (column.name === 'status' && row.status === 0) {
return { color: '#f56c6c', fontWeight: 'bold' }
}
return {}
},
// 表头单元格样式
headerStyle({ column, columnIndex }) {
if (column.name === 'salary') {
return { color: '#e6a23c' }
}
return {}
}
}
动态操作按钮权限
通过 permissionBtn 根据行数据动态控制操作按钮的显示隐藏。
<zb-table
:columns="columns"
:data="data"
:permission-btn="filterButtons"
@edit="onEdit"
@delete="onDelete"
></zb-table>
columns: [
{ name: 'name', label: '姓名' },
{ name: 'operation', type: 'operation', label: '操作', renders: [
{ name: '编辑', func: 'edit' },
{ name: '删除', type: 'warn', func: 'delete' },
{ name: '查看', type: 'custom', func: 'view' }
]}
],
methods: {
// 返回需要显示的按钮数组
filterButtons(row, renders, index) {
if (row.disabled) {
return renders.filter(r => r.func !== 'delete') // 禁用行不显示删除按钮
}
return renders
}
}
自定义合计行
通过 summaryMethod 自定义合计行的计算逻辑。
<zb-table
:columns="columns"
:data="data"
show-summary
sum-text="合计"
:summary-method="getSummaries"
></zb-table>
methods: {
getSummaries({ columns, data }) {
const sums = []
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = '总计'
return
}
if (column.name === 'salary') {
const values = data.map(item => Number(item[column.name]))
sums[index] = values.reduce((prev, curr) => prev + curr, 0).toLocaleString()
} else {
sums[index] = '--'
}
})
return sums
}
}
微信小程序插槽
微信小程序不支持动态具名插槽,需同时设置 slot 和 tableCell 属性。
<!-- 非微信小程序平台 -->
<zb-table :columns="columns" :data="data">
<template #statusSlot="{ row, column, index }">
<text :style="{ color: row.status === 1 ? 'green' : 'red' }">
{{ row.status === 1 ? '在线' : '离线' }}
</text>
</template>
</zb-table>
<!-- 微信小程序平台 -->
<zb-table :columns="columns" :data="data">
<template #tableCell="{ row, column, index }">
<view v-if="column.name === 'status'">
<text :style="{ color: row.status === 1 ? 'green' : 'red' }">
{{ row.status === 1 ? '在线' : '离线' }}
</text>
</view>
</template>
</zb-table>
// 非微信小程序
columns: [
{ name: 'status', label: '状态', slot: 'statusSlot' }
]
// 微信小程序(需同时设置 slot 和 tableCell)
columns: [
{ name: 'status', label: '状态', slot: 'statusSlot', tableCell: 'tableCell' }
]
列宽自适应与自动分配
<!-- fit 模式:根据内容自动计算列宽 -->
<zb-table :columns="columns" :data="data" :fit="true"></zb-table>
<!-- 非fit模式:未设置width的列默认100px,列宽总和不足容器时自动平均分配剩余空间 -->
<zb-table :columns="columns" :data="data"></zb-table>
行为说明:
fit=true时,列宽根据表头文字和数据内容自动计算,用户拖拽过的列不会再次自动适配fit=false(默认)时,未设置width的列默认 100px;当所有列宽总和小于容器宽度时,剩余空间会平均分配给未显式设置width的列- 用户手动拖拽调整过的列(
_userResized)不会被自动分配覆盖- 可通过
minWidth设置列的最小宽度,避免列被压缩过小
多选 Checkbox
设置 type: 'selection' 列即可启用多选功能,支持单选、全选、初始选中、获取选中数据。
<zb-table
ref="zbTable"
:columns="columns"
:data="data"
row-key="id"
@toggleRowSelection="onRowSelect"
@toggleAllSelection="onAllSelect"
></zb-table>
columns: [
{ type: 'selection', fixed: true, width: 50 },
{ name: 'name', label: '姓名', width: 80 },
{ name: 'age', label: '年龄', width: 80 }
],
data: [
{ id: 1, name: '张三', age: 25, checked: true }, // checked: true 初始选中
{ id: 2, name: '李四', age: 30 },
{ id: 3, name: '王五', age: 28, checked: true }
],
methods: {
// 单行选中变化
onRowSelect(selected, selectedArray) {
console.log('当前选中状态:', selected)
console.log('已选中行:', selectedArray)
},
// 全选变化
onAllSelect(selected, selectedArray) {
console.log('全选状态:', selected)
console.log('已选中行:', selectedArray)
},
// 主动获取选中行
getSelected() {
const selected = this.$refs.zbTable.getSelection()
console.log('当前选中行:', selected)
},
// 清除所有选中
clearSelected() {
this.$refs.zbTable.clearSelection()
}
}
行高亮
设置 highlight 启用行高亮,点击行时高亮显示并触发 currentChange 事件。
<zb-table
:columns="columns"
:data="data"
:highlight="true"
row-key="id"
@currentChange="onCurrentChange"
></zb-table>
methods: {
onCurrentChange(row, index) {
console.log('选中行:', row)
console.log('行索引:', index)
},
// 手动清除高亮
clearHighlight() {
this.$refs.zbTable.resetHighlight()
}
}
说明:高亮行背景色为
#ecf5ff,可通过 CSS 覆盖.current-row .item-td样式自定义。
自定义排序
设置 sorter: 'custom' 启用自定义排序,排序时触发 sort-change 事件,由业务方自行处理数据排序。
<zb-table
:columns="columns"
:data="data"
@sort-change="onSortChange"
></zb-table>
columns: [
{ name: 'name', label: '姓名' },
{ name: 'salary', label: '薪资', sorter: 'custom' }, // 自定义排序
{ name: 'joinDate', label: '入职日期', sorter: 'custom' }
],
methods: {
onSortChange(column, order, columnIndex) {
// column: 列配置对象
// order: 'asc' 或 'desc'
// columnIndex: 列索引
console.log(`按 ${column.name} 列 ${order} 排序`)
// 自行请求后端排序接口或前端排序
this.loadData({ sortField: column.name, sortOrder: order })
}
}
说明:
sorter: true(内置排序)由组件内部完成排序,支持数值、日期、中文自然排序(如 "DF-5C" 正确识别数字部分)。sorter: 'custom'适用于服务端排序场景。
组合场景:多选 + 分页
多选与分页组合使用时,建议设置 rowKey 以保持跨页选中状态稳定。
<zb-table
ref="zbTable"
:columns="columns"
:data="pageData"
row-key="id"
:pagination="true"
:current-page.sync="currentPage"
:page-size="pageSize"
:total="total"
@toggleRowSelection="onRowSelect"
@pageChange="onPageChange"
></zb-table>
columns: [
{ type: 'selection', fixed: true, width: 50 },
{ name: 'name', label: '姓名' },
{ name: 'age', label: '年龄' }
],
methods: {
onPageChange({ currentPage, pageSize }) {
this.currentPage = currentPage
this.fetchData(currentPage, pageSize)
},
onRowSelect(selected, selectedArray) {
// 跨页选中状态通过 rowKey 保持
this.selectedRows = selectedArray
}
}
组合场景:左固定 + 右固定 + 多级表头
同时使用左右固定列和多级表头的完整示例。
columns: [
{ type: 'selection', fixed: true, width: 50 },
{ name: 'name', label: '姓名', fixed: true, width: 80 },
{
label: '基本信息',
children: [
{ name: 'age', label: '年龄', width: 80 },
{ name: 'sex', label: '性别', width: 80, filters: { 0: '男', 1: '女' } }
]
},
{
label: '地址信息',
children: [
{ name: 'province', label: '省份', width: 100 },
{ name: 'city', label: '城市', width: 100 }
]
},
{ name: 'date', label: '日期', width: 120, sorter: true },
// 右固定操作列
{ name: 'operation', type: 'operation', label: '操作', fixed: 'right', width: 150, renders: [
{ name: '编辑', func: 'edit' },
{ name: '删除', type: 'warn', func: 'dele' }
]}
]
说明:父列设置
fixed时,子列会自动继承。多级表头中固定列的判定以叶子列为准。
工具栏(列设置面板)
设置 toolbar 属性后,表格顶部会出现工具栏,用户可通过列设置面板动态调整列的显隐、对齐方式、固定方式和排列顺序。
<zb-table
:columns="columns"
:data="data"
:toolbar="true"
@column-change="onColumnChange"
>
<!-- 工具栏左侧可放置自定义内容 -->
<template #toolbar>
<text class="toolbar-title">数据列表</text>
</template>
</zb-table>
methods: {
onColumnChange({ type, column, value }) {
// type: 'visible' | 'align' | 'fixed' | 'order'
// column: 变化的列配置对象
// value: 变化后的值
console.log(`列 ${column.name} 的 ${type} 变为 ${value}`)
// 可在此持久化用户列配置(如存入 localStorage)
if (type === 'visible') {
console.log(column.name, value ? '显示' : '隐藏')
} else if (type === 'align') {
console.log(column.name, '对齐方式', value)
} else if (type === 'fixed') {
console.log(column.name, '固定方式', value)
} else if (type === 'order') {
console.log(column.name, '移动到位置', value)
}
}
}
工具栏面板功能:
- 列显隐:点击列名前的复选框切换显隐
- 对齐方式:左对齐/居中/右对齐
- 固定方式:左固定/右固定/取消固定
- 列排序:拖拽排列或点击上移/下移按钮调整列顺序
selection和index类型列不在面板中显示- 设置了
hidden: true的列在面板中默认为未选中状态,可通过面板重新显示
单选模式
设置 singleSelect 后,selection 列显示为单选框,同一时间只能选中一行。
<zb-table
:columns="columns"
:data="data"
:single-select="true"
row-key="id"
@toggleRowSelection=""
></zb-table>
columns: [
{ type: 'selection', width: 50 },
{ name: 'name', label: '姓名' },
{ name: 'age', label: '年龄' }
],
methods: {
(selected, selectedArray) {
// selected: Boolean(当前行是否选中)
// selectedArray: 选中行数组(单选模式下最多1个元素)
console.log('选中行:', selectedArray)
}
}
说明:
singleSelect=true时,全选复选框不显示,点击某行单选框会自动取消之前选中的行。
禁止内容复制
设置 disableCopy 后,表格内容不可被鼠标选中复制,适用于数据安全场景。
<zb-table
:columns="columns"
:data="data"
:disable-copy="true"
></zb-table>
自定义行样式
通过 rowStyle 设置整行样式,优先级低于 cellStyle。
<zb-table
:columns="columns"
:data="data"
:row-style="rowStyle"
></zb-table>
methods: {
rowStyle({ row, rowIndex }) {
if (row.expired) {
return { backgroundColor: '#fef0f0', color: '#f56c6c' }
}
if (rowIndex % 2 === 0) {
return { backgroundColor: '#f0f9ff' }
}
return {}
}
}
隐藏列
设置 hidden: true 可初始隐藏列,后续可通过工具栏面板重新显示。
columns: [
{ name: 'name', label: '姓名' },
{ name: 'age', label: '年龄' },
{ name: 'salary', label: '薪资', hidden: true }, // 初始隐藏
{ name: 'address', label: '地址' }
]
说明:
hidden为列的初始状态,配合toolbar使用时用户可在面板中重新勾选显示。
注意事项
-
rowKey 推荐设置:树形表格和多选模式下,强烈建议设置
rowKey(如"id"),以确保行唯一标识稳定。未设置时使用数组索引,数据增删后可能导致选中状态异常。 -
列宽计算:组件内部统一使用
transColumns作为列宽数据源,表头、表体、合计行宽度保持一致。未设置width的列默认 100px。 -
列宽拖拽与自动分配:用户手动拖拽调整过的列宽会被标记(
_userResized),不会被后续的自动平均分配覆盖。如需重置,修改 columns 的 width 值即可。 -
微信小程序插槽限制:微信小程序不支持动态具名插槽,必须同时设置
slot和tableCell属性,且插槽名固定为tableCell,在插槽内通过column.name判断当前列。 -
树形异步懒加载:只有数据项显式包含
hasChildren: true才会显示展开箭头并触发treeLoad,否则视为叶子节点。treeLoad函数中需调用resolve(childrenArray)完成加载。 -
排序模式:
sorter: true为内置排序(支持数值/日期/中文自然排序),sorter: 'custom'为自定义排序(触发sort-change事件,需自行处理数据排序)。 -
固定列显示条件:左/右固定列面板仅在内容宽度超出容器时才会启用,内容未超出时固定列与普通列一致显示,避免重复。
-
数据响应式:修改
data或columns后组件会自动更新。小程序端可能需要$forceUpdate辅助刷新,组件内部已处理。 -
图片列:
type: 'img'的列支持字符串(单图)和数组(多图)格式,点击图片会调用uni.previewImage预览。 -
上拉加载 vs 懒加载状态机:推荐使用
lazyLoad懒加载状态机替代传统isShowLoadMore,状态机提供 loading/noMore/error 三种状态,交互体验更好。 -
pullUpLoading prop 与事件:
pullUpLoading既是 prop(Function 类型,传入回调函数)也是事件(通过@pullUpLoading监听)。使用 prop 方式可调用done()控制加载状态;使用事件方式需手动调用this.$refs.zbTable.pullUpCompleteLoading('ok')结束加载。 -
sorter: false 的行为:
sorter默认为false,表示该列不显示排序图标。设置为true显示排序图标并由组件内部排序,设置为'custom'显示排序图标但由业务方处理排序逻辑。 -
多级表头中固定列的继承:父列设置
fixed时,其子列会自动继承fixed和align属性(子列未显式设置时)。多级表头中固定列的判定以叶子列为准。 -
columns 不可变约定:组件内部会对 columns 进行深克隆处理,不会修改原始 props。但直接修改 columns 数组引用(如
this.columns = newColumns)才会触发组件重新计算,修改数组内部对象的属性需使用this.$set。 -
工具栏列配置持久化:工具栏中的列显隐、对齐、固定、排序等操作仅在当前会话生效。如需持久化用户列配置,监听
column-change事件并将配置存入 localStorage,初始化时从 localStorage 恢复 columns 配置即可。 -
单选模式:
singleSelect=true时,全选复选框不显示,点击任意行单选框会自动取消之前选中的行。toggleRowSelection事件回调中selectedArray最多包含 1 个元素。 -
隐藏列:
column.hidden=true为初始隐藏状态,不影响数据渲染逻辑,仅控制列是否在表头和表体中可见。配合toolbar使用时用户可在列设置面板中重新勾选显示。
兼容平台
| 平台 | 支持情况 |
|---|---|
| H5(PC 浏览器) | Chrome / IE / Edge / Firefox / Safari ✅ |
| H5(移动浏览器) | Safari / Android Browser / 微信浏览器 / QQ浏览器 ✅ |
| App (Vue) | ✅ |
| App (nVue) | ⚠️ 部分支持 |
| 微信小程序 | ✅ |
| 阿里小程序 | ✅ |
| 百度小程序 | ✅ |
| 字节跳动小程序 | ✅ |
| QQ 小程序 | ✅ |
| 快应用(华为/联盟) | ✅ |
更新日志
详见 changelog.md

收藏人数:
购买源码授权版(
试用
使用 HBuilderX 导入示例项目
赞赏(0)
下载 0
赞赏 0
下载 12390355
赞赏 1928
赞赏
京公网安备:11010802035340号