更新记录

2.0.0(2026-11-01)

核心引擎

  • 纯 Canvas 2D 渲染,零 DOM 表格;行 + 主区列双虚拟化,2 万行流畅滚动。
  • 固定列(左 / 右)与边缘阴影、冻结行、多级表头、汇总页脚。
  • 排序(多列)、筛选、树形(含懒加载)、逻辑分页。
  • rowKey 受控选择、合并单元格、变高行、自定义渲染器。
  • 惯性滚动 + 边界回弹;浅色 / 暗色主题 + 自定义色板。
  • 高倍屏(dpr 2/3)按运行环境区分「位图已缩放 / 需自行缩放」,移动端不再只画出表格一角。

渲染与交互修正(首版发布前修复)

  • H5 首屏不再「只渲染左上角一块」:uni-app 的 H5 canvas 上下文带 __hidpi__(平台已把坐标乘过 dpr),旧实现又额外 setTransform(dpr),缩放叠加成 dpr²。现由 contextScaled 标记区分,原生端仍按 dpr。
  • 固定列里的高亮不再消失:激活框 / 框选 / 查找命中改为按「左固定 / 主区 / 右固定」三条竖带逐段裁剪,既不越界也不画不出来。
  • 被固定列盖住的主区列不再露出手柄:列宽手柄与拖拽指示线的绘制、命中共用同一份「本带内是否可见」判据。
  • 冻结行上的行高拖拽命中正确的行(旧实现按屏幕坐标反查,改的是屏幕外那行)。
  • 右侧固定列阴影只在右边还有内容时出现,无横向余量时不再常驻。
  • 键盘方向键会把激活格横向滚入视口(此前只滚纵向),与查找的「滚入视口」收敛为一份实现。
  • 单层绘制异常不再让整表被裁成一条:裁剪统一走 paint.withClip(),异常路径也保证 restore。
  • 窗口尺寸变化后文字不再上移:canvas.width = 会静默重置 2D 上下文(字体 / 基线 / 对齐回默认),而 Paint.bind() 因 ctx 引用未变而早退;现在位图尺寸变更后强制 paint.resetCtx() 重发状态。
  • resize 不再闪一帧空白:canvas 尺寸只在 render 帧首修改,避免「清空画布 → 下一帧才重绘」的中间透明白帧。

主题

  • 可覆盖字段 37 个,全部生效;theme 传 null = 撤掉全部覆盖,切 dark 同理。
  • 暗色滚动条按主题灰阶重做:轨道取表头色半透明(贴合任意行色,不再出现比行更黑的竖条),滑块 #5d6875、拖拽态 #93a2b3,与正文形成四级递进。
  • 暗色 tooltip 浮层提亮至 rgba(53,60,71,.96),不再与背景融成一片。

数据筛选

  • 受控 prop filters({ 列的 key 或 field: 值 },多条件 AND),filterMethod 提供表级自定义匹配,列级优先。
  • 内置匹配按值类型分派:字符串 = 包含、数组 = IN、数字 / 布尔 = 等价比较;'' / [] / null 视为不筛。
  • 事件 filter-change 只在 setFilters / clearFilters 后回抛,改 prop 不抛(避免受控侧死循环)。
  • 与分页 / 树 / 分组叠加,顺序为「先筛选 → 再分页 / 建树 / 分组」。
  • 组件不画筛选 UI:入口由业务自建,改 filters 即生效。

交互能力

  • 列宽 / 行高拖拽:常驻手柄,移动端按输入源自动取长按阈值,按下即反馈。
  • 行拖拽排序(rowReorder)、列拖拽重排(columnReorder),落位回抛新顺序。
  • 列显隐 / 列选择器;条件格式(cellStyle → conditional → 主题)。
  • 行选择:行级勾选与单元格选区两套独立 API。

行内编辑

  • editable 一处开关,串起编辑 → 校验 → 历史。
  • 双击 / Enter / F2 三入口;列级 editType(text / number / textarea);只读、序号、手柄、分组行自动拒编。
  • 事件 edit-commit / edit-cancel,携带 rowKey / field / oldValue / newValue / valid / message。
  • 键盘导航、TSV 复制粘贴、校验(required / number / integer / email / regex / min / max / custom)、撤销重做。

分组 / 聚合

  • groupBy + 列级 aggregate;组头为行投影伪行,虚拟滚动 / 导出全自动,与页脚口径独立。

导出

  • exportImage() 导出当前帧位图(返回值随运行环境而定,可能是 data URL 或临时文件路径),只生成不落盘。
  • getExportData() 返回 { columns, rows };exportCsv() 返回纯字符串 CSV。

插件化

  • registerCellRenderer / registerCellEditor 支持自定义类型而不改引擎。
  • table.use() 全局插件注册表;TooltipPlugin 拆为独立产物(core-tooltip.esm.min.js,2.2kb)按需启用。

文档与类型

  • 44 个 prop 的说明在四处(props.ts / TableProps / l-table-x.uvue / l-table-x.vue)逐字一致,字段顺序统一,说明只保留一句话作用,并由 unit_props_alignment 守卫。
  • props.ts 去掉 as PropType<...> 断言:类型契约统一由 TableProps 承载,运行时对象只留 type / default。
  • 对外类型注释精简,去掉版本注记与长篇取舍叙述。
  • readme 顶部补插件元信息(name / description / tags / componentTag / plugin / category / dependencies),与「插件标签说明」表及真实依赖保持一致。
  • 插件文档收敛为 readme.md 单文件:68 个实例方法、37 个主题字段(含浅色 / 暗色默认值)、ColumnDefine 等类型定义全部内联,不再引用 docs/ 目录,包内 docs/ 与 build:docs 一并移除。

示例

  • 示例画廊六个分类:基础 / 选择 / 树形 / 表头渲染 / 分组聚合 / 编辑导出。
  • 移动端一屏可见:控制区压到最小,说明文字下移,表格高度按视口自适应;390×844 下六个分类均无溢出。

平台兼容性

uni-app(5.31)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
√ √ √ √ √ - √ √ √
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
√ - - - - - - - - - - -

uni-app x(5.31)

Chrome Safari Android iOS 鸿蒙 微信小程序
√ √ √ √ √ √

其他

多语言 暗黑模式 宽屏模式 蒸汽模式
× × × √

name: lime-table-x 高性能表格组件 description: 高性能表格组件,纯 Canvas 2D 绘制,行与主区列双向虚拟化,支持固定列、冻结行、多级表头、排序、筛选、树形、分组聚合、行内编辑与导出,2 万行流畅滚动,适用于数据列表、报表、后台管理等场景。 tags:

  • table
  • 表格
  • canvas
  • 虚拟滚动
  • 高性能
  • 数据展示 componentTag: l-table-x plugin: lime-table-x category: 展示组件 dependencies:
  • lime-shared

lime-table-x 高性能 Canvas 表格

一款纯 Canvas 2D 绘制的 uni-app / uni-app x 表格组件:零 DOM 表格结构,行 + 主区列双向虚拟化,2 万行流畅滚动。支持固定列 / 冻结行 / 多级表头 / 排序 / 筛选 / 树形 / 分组聚合 / 行内编辑 / 导出。

插件依赖:lime-shared

安装方法

  1. 在 uni-app 插件市场中搜索并导入 lime-table-x
  2. 确保依赖 lime-shared 已安装(首次导入后可能需要重新编译项目)
  3. 在页面中使用 <l-table-x> 组件

代码演示

基础用法

通过 :data 与 :columns 传入数据与列定义即可。

<l-table-x
    ref="tableRef"
    :data="data"
    :columns="columns"
    row-key="id"
    width="100%"
    :height="430"
    @cell-click="onCellClick" />
import { ref } from 'vue'

const tableRef = ref(null)
const data = ref([
    { id: 1, name: '用户1', email: 'user1@example.com' },
    { id: 2, name: '用户2', email: 'user2@example.com' }
])
const columns = ref([
    { field: 'id', title: 'ID', width: 80 },
    { field: 'name', title: '姓名', width: 120 },
    { field: 'email', title: '邮箱', width: 160 }
])
const onCellClick = (info) => {
    console.log('点击单元格:', info.rowIndex, info.field, info.value)
}

固定列 / 排序 / 汇总页脚

fixed 固定左 / 右列,sortable 开启排序,列级 footer 声明全表汇总口径。

const columns = [
    { field: 'id', title: 'ID', width: 72, fixed: 'left', sortable: true },
    { field: 'name', title: '姓名', width: 110, fixed: 'left' },
    { field: 'salary', title: '薪资', width: 120, align: 'right', sortable: true, footer: { type: 'sum' } }
]
<l-table-x :data="data" :columns="columns" :footer-height="40" @sort-change="onSort" />

footer 与 aggregate 支持 sum / avg / count / min / max / custom(fn)/ text(固定文案)。

多级表头与合并单元格

列上写 children 即多级表头;span 返回 { rowspan, colspan } 声明合并(两者都必填)。

const columns = [
    {
        title: '基本信息',
        children: [
            { field: 'id', title: 'ID', width: 80 },
            { field: 'name', title: '姓名', width: 120 }
        ]
    },
    { field: 'dept', title: '部门', width: 120, span: (row) => ({ rowspan: 2, colspan: 1 }) }
]

树形(含懒加载)

tree 配置开启树形,childrenKey 指定子节点字段,lazy + load 实现异步懒加载。

// 预置子节点
const tree = { childrenKey: 'children', defaultExpandAll: false }

// 懒加载(点开才拉取子节点)
const treeLazy = {
    childrenKey: 'children',
    lazy: true,
    load: (row) => fetchChildren(row)   // 返回 Promise<any[]>
}
<l-table-x :data="data" :columns="columns" :tree="tree" :indent="20" @row-expand="onExpand" />

分组 / 聚合

groupBy 按字段分组,组头行跟随虚拟滚动;列级 aggregate 声明组内口径。

const groupBy = { field: 'dept', defaultExpanded: true }
const columns = [
    { field: 'dept', title: '部门', width: 120 },
    { field: 'salary', title: '薪资', width: 120, aggregate: { type: 'avg' } }
]
<l-table-x :data="data" :columns="columns" :group-by="groupBy" @group-toggle="onGroupToggle" />

受控展开态::group-expanded-keys + @update:group-expanded-keys。

数据筛选(受控)

filters 是受控筛选值 { 列的 key 或 field: 值 },多条件取 AND;组件不画筛选 UI,入口自己画(表头菜单 / 搜索框 / 外部表单),改值即生效。

内置匹配够用就不必写 filterMethod:字符串 = 包含(忽略大小写)、数组 = IN、数字与布尔 = 等价比较;'' / [] / null 视为不筛。

<l-table-x :data="data" :columns="columns" :filters="filters" @filter-change="" />
const filters = ref({ name: '张', dept: ['研发部', '财务部'] })   // 姓名含「张」且部门属于两者之一

const  = ({ filters: f, count }) => {
    console.log('筛选后行数', count)   // 只在调 setFilters / clearFilters 时回抛,改 props 不抛
}

// 内置表达不了的(日期 / 数值区间):值可以是任意对象,交给 filterMethod 解释
const filterMethod = (v, row) => row.salary >= v[0] && row.salary <= v[1]
// filters: { salary: [3000, 8000] }

行内编辑与校验

editable 一处开关开启编辑;列上 editType: 'text' | 'number' | 'textarea',editable: false 置灰。双击 / Enter / F2 进入编辑,Enter 提交、Esc 取消。

const columns = [
    { field: 'name', title: '姓名', width: 120, editType: 'text' },
    {
        field: 'salary', title: '薪资', width: 120, editType: 'number',
        validators: [{ type: 'required' }, { type: 'min', value: 0 }]
    },
    { field: 'id', title: 'ID', width: 80, editable: false }
]
<l-table-x :data="data" :columns="columns" editable @edit-commit="onCommit" />

配套实例方法:beginEditCell / commitEdit / cancelEdit / undoEdit / redoEdit / pasteText。

自定义单元格

render(params) 函数式绘制,注入 drawText / drawRoundRect / drawCircle / drawPolyline / drawSmoothLine / drawArea / registerClickArea(禁止返回 VNode;后三个为点集原语,画 sparkline / 趋势图)。

const columns = [
    {
        field: 'op', title: '操作', width: 150,
        render: (p) => {
            p.drawRoundRect(p.rect.x + 10, p.rect.y + 10, 60, 24, 5, '#2f7ef7', null)
            p.drawText('查看', p.rect.x + 10, p.rect.y + p.rect.height / 2, 60, '#ffffff', 'center')
            p.registerClickArea(
                { x: p.rect.x + 10, y: p.rect.y + 10, width: 60, height: 24 },
                () => console.log('点击查看', p.row)
            )
        }
    }
]

条件格式

列上 cellStyle(函数式)或 conditional(声明式规则数组),优先级:cellStyle → conditional → 主题。

const columns = [
    {
        field: 'salary', title: '薪资', width: 120,
        conditional: [
            { when: (row) => row.salary > 20000, style: { backgroundColor: '#fff1f0' } },
            { when: (row) => row.salary < 5000, style: { backgroundColor: '#f0f9ff' } }
        ]
    }
]

列宽 / 行高拖拽

colResizable 默认开(按列 resizable: false 可单独关闭),rowResizable 默认关(会占用数据区的纵向拖拽手势)。showResizeHandle 控制是否常驻显示手柄短线。

<l-table-x :data="data" :columns="columns" row-resizable show-resize-handle
           @column-width-change="onColWidth" @row-height-change="onRowHeight" />

移动端与桌面共用一份实现:鼠标按下即拖,手指需长按(阈值由 resizePressDelay 控制,-1 = 按输入源自适应)。

导出

exportImage() 无参导出当前渲染画面位图(只生成不落盘);getExportData() 返回结构化行列,可接任意 xlsx 库自建 Excel 导出;exportCsv() 返回纯字符串 CSV。

const img = await tableRef.value?.exportImage()   // 返回值随运行环境而定:data URL 或临时文件路径
const { columns, rows } = tableRef.value?.getExportData()
const csv = tableRef.value?.exportCsv()

可选插件(tooltip 浮层)

浮层提示(文本溢出 / 校验错误文案)默认不打包,需要时从独立产物启用一次即可——全局启用:

import { table } from '@/uni_modules/lime-table-x'
import { TooltipPlugin } from '@/uni_modules/lime-table-x/plugins/tooltip'

// use() 不做去重,重复注册会重复挂图层(浮层画两遍);在可能多次调用的地方先判一下
if (table.plugins().indexOf(TooltipPlugin) < 0) table.use(TooltipPlugin)

只让某一张表启用:tableRef.value.usePlugin(TooltipPlugin)。

自定义插件

插件是一个普通对象 / 类,install(engine) 里挂图层或订阅信号即可(usePlugin 传类或实例都行,引擎未就绪时自动缓冲):

import type { TablePlugin } from '@/uni_modules/lime-table-x'

const MyPlugin: TablePlugin = {
    name: 'my-plugin',
    install(engine) { /* 注册时调用一次:engine.addLayer(...) / 订阅信号 */ },
    onBeforeRender(state) { /* 每帧在重绘前调用:把状态写进 RenderState,必须纯函数 */ },
    dispose() { /* 引擎销毁时清理,需幂等 */ }
}

tableRef.value?.usePlugin(MyPlugin)

API 文档

Props 分类

🎯 基础配置(最常用)

参数 说明 类型 默认值 可选值
data 表格数据(行对象数组) any[] [] -
columns 列定义,支持 children 多级表头 ColumnDefine[] [] -
width 表格宽度:数字为 px,字符串支持百分比 number | string '100%' -
height 表格高度:数字为 px,字符串支持百分比 number | string 300 -
rowHeight 行高(px) number 44 -
headerHeight 表头单层高度(px),多级表头逐层累加 number 44 -
footerHeight 页脚高度(px),0 = 不显示 number 0 -
fontSize 基础字号(px) number 14 -
rowKey 行主键字段名 string 'id' -

🎨 主题与外观

参数 说明 类型 默认值 可选值
stripe 斑马纹 boolean true true, false
hover 悬浮高亮 boolean true true, false
dark 暗色主题 boolean false true, false
theme 主题色板覆盖 TableTheme - -
cellStyle 旧版兼容:单元格样式(等价 theme) TableCellStyle - -

✅ 选择 / 编辑 / 拖拽

参数 说明 类型 默认值 可选值
showCheckbox 显示复选框列 boolean false true, false
selectedRowKeys 受控选中行 key string[] [] -
selectionOverridesCellStyle 选中底色是否覆盖单元格底色 boolean true true, false
cellNavigation 键盘导航开关(方向键移动激活格) boolean true true, false
cellSelection 单元格选区开关(Shift 框选 / Ctrl+A) boolean true true, false
editable 行内编辑开关(双击 / Enter 进入编辑) boolean false true, false
rowReorder 行拖拽排序(左侧手柄列) boolean false true, false
columnReorder 列拖拽重排 boolean false true, false
frozenRowCount 冻结行数(钉在表体顶部) number 0 -
rowResizable 行高拖拽开关 boolean false true, false
colResizable 列宽拖拽开关 boolean true true, false
showResizeHandle 常驻显示拖拽手柄短线 boolean false true, false
resizePressDelay 拖拽长按阈值(ms),-1 = 按输入源自动 number -1 -
resizeScrollGuard 滚动优先窗口(ms),0 = 关闭 number 240 -

🌲 树形与分组

参数 说明 类型 默认值 可选值
tree 树形配置 TreeConfig - -
indent 树形缩进(px) number 20 -
groupBy 分组 / 聚合配置 GroupConfig - -
groupHeaderHeight 组头行高(px),0 = 与普通行同高 number 0 -
groupExpandedKeys 受控展开组 key string[] - -

🔍 数据筛选

参数 说明 类型 默认值 可选值
filters 受控筛选值(列 key → 值,多列 AND) FilterMap - -
filterMethod 表级自定义筛选匹配 FilterMethod - -

📄 分页与文案

参数 说明 类型 默认值 可选值
pageSize 每页条数,0 = 不分页 number 0 -
currentPage 当前页(1 起) number 1 -
locale 内置文案语言 string 'zh-CN' zh-CN, en-US
emptyText 空数据文案(留空取语言包) string '' -
loading 加载中(遮罩 + 文案) boolean false true, false

⚡ 性能与滚动

参数 说明 类型 默认值 可选值
overscan 虚拟滚动缓冲区行数 number 4 -
degradeOnScroll 快滚降级(缩小 overscan、跳过静止方向网格线) boolean true true, false
settleDelay 滚动停止后补帧延迟(ms) number 40 -
scrollbar 自定义滚动条显隐 string 'auto' auto, always, none

Events

事件名 说明 回调参数
cell-click 点击单元格 CellInfo(行 / 列下标、field、value、row、rect)
row-click 点击行(含落点列信息) CellInfo
header-click 点击表头 ColumnNode
sort-change 排序变化 { key, order, states }
selection-change 行勾选集合变化 { keys, rows }
row-select 单行勾选(先于 selection-change) { key, row, rowIndex, checked, keys, rows }
select-all 表头全选 / 全不选(先于 selection-change) { checked, keys, rows }
update:selectedRowKeys 配合 v-model:selected-row-keys string[]
scroll 滚动(已节流) { top, left, maxTop, maxLeft }
row-expand 树形展开 / 收起 { row, expanded }
reach-bottom 纵向滚动触底(加载更多) -
column-width-change 列宽拖拽结束 { column, key, width }
row-height-change 行高拖拽结束 { rowIndex, height }
range-selection-change 单元格框选变化 { r0, c0, r1, c1 } \| null
ready 引擎初始化完成(canvas 就绪) -
row-reorder 行拖拽落位(order = 重排后的数据) { fromIndex, toIndex, order }
column-reorder 列拖拽重排落位 { fromKey, toIndex, order }
column-visible-change 列显隐变化 { key, visible, hiddenKeys }
group-toggle 分组展开 / 收起 { key, value, count, expanded, expandedKeys }
update:groupExpandedKeys 配合 v-model:group-expanded-keys string[]
edit-commit 提交编辑 { rowKey, field, oldValue, newValue, valid, message }
edit-cancel 取消编辑 { rowKey, field, value }
filter-change 筛选变化(仅 setFilters / clearFilters 触发) { filters, count }

实例方法(通过 ref)

实例上共 68 个公开方法,按用途分组(方法名与 TableInstance 类型逐项一致)。

布局与滚动(7)

方法 说明 返回
resize() 重新测量容器并重算布局(容器尺寸变了但窗口没变时调) Promise<void>
scrollTo(x, y, animated?) 滚动到指定偏移(逻辑 px) void
scrollToIndex(index) 滚动到指定行 void
setColumnWidth(key, width) 编程式设列宽,会回抛 column-width-change void
setRowHeight(index, height) 编程式设行高(按行下标) void
getColumnRect(key) 列在视口内的矩形(浮层对齐 / 自动化测试用) Rect \| null
getRowRect(index) 行在视口内的矩形(同上) Rect \| null

排序与筛选(6)

方法 说明 返回
clearSort() 清空全部列的排序态 void
setFilters(filters) 设置筛选值,会回抛 filter-change void
clearFilters() 清空全部筛选 void
getFilters() 当前生效的筛选值(只读引用) FilterMap
getFilteredCount() 筛选后、分页前的行数 number
isFiltered() 是否有任意一列筛选生效('' / [] / null 不算) boolean

行选择(4)

方法 说明 返回
getSelectedKeys() 选中行 key(顺序 = 当前数据顺序) string[]
getSelectedRows() 选中行对象 any[]
clearRowSelection() 清空行勾选(≠ clearSelection) void
selectAllRows(checked?) 全选 / 全不选,返回选中 key string[]

单元格选区与剪贴板(8)

方法 说明 返回
getSelection() 当前选区,无选区返回 null { r0, c0, r1, c1 } \| null
setActiveCell(row, col) 设置激活格(按行列下标) void
setRange(ar, ac, fr, fc) 设置选区(锚点行 / 列 → 焦点行 / 列) void
clearSelection() 清空单元格选区 void
scrollActiveIntoView() 把激活格滚进视口 void
copySelection() 复制选区为 TSV 并写入剪贴板 string
pasteText(tsv) 粘贴 TSV 文本(不读剪贴板) void
pasteFromClipboard() 读剪贴板并粘贴(部分平台需用户手势) void

查找(5)

方法 说明 返回
find(keyword) 跳到首个命中并高亮,返回命中行数 number
findNext() 下一个命中 FindResult \| null
findPrev() 上一个命中 FindResult \| null
clearFind() 清除查找态 void
getFindResult() 当前查找状态 FindResult

行内编辑(9)

方法 说明 返回
beginEditCell(row, col) 进入编辑态,不可编辑返回 false boolean
commitEdit(value) 提交编辑(校验 → 记历史 → emit edit-commit) void
cancelEdit() 取消编辑 void
isEditing() 是否处于编辑态 boolean
getValueByKey(key, field) 按行 key + 字段取值 any
undoEdit() 撤销上一次编辑 void
redoEdit() 重做 void
canUndoEdit() 是否可撤销 boolean
canRedoEdit() 是否可重做 boolean

列显隐(5)

方法 说明 返回
setColumnVisible(key, visible) 显示 / 隐藏列,返回是否生效(最后一列不可隐藏) boolean
getColumnVisible(key) 某列当前是否可见 boolean
getColumnList() 全部叶列(含已隐藏),供业务渲染列选择器 ColumnNode[]
getHiddenColumnKeys() 当前被隐藏的列 key string[]
resetColumnVisibility() 一次性显示全部列 void

分组(6)

方法 说明 返回
setGroupBy(cfg) 运行时切分组,传 null 关闭 void
toggleGroup(key) 展开 / 收起某组,返回操作后的展开态 boolean
expandAllGroups() 展开全部组 void
collapseAllGroups() 收起全部组 void
getGroupKeys() 全部组 key string[]
getExpandedGroupKeys() 当前展开的组 key string[]

数据与行序(3)

方法 说明 返回
updateData(data) 显式提交数据(原地改数组后调用,绕过引用去重) void
updateColumns(columns) 显式提交列定义 void
reorderRow(from, to) 把第 from 行移到 to 行,回抛 row-reorder void

导出(3)

方法 说明 返回
exportCsv(delimiter?) 导出可见数据为 CSV 字符串(纯数据,落盘由调用方处理) string
exportImage() 导出位图(H5 返回 dataURL,原生返回临时文件路径) Promise<string>
getExportData() 全部列 + 全部行的结构化数据(不受视口裁剪) { columns, rows }

渲染器与插件(6)

方法 说明 返回
registerCellRenderer(type, impl) 注册自定义单元格渲染器(按列 type 分发) void
unregisterCellRenderer(type) 注销渲染器 void
registerCellEditor(type, impl) 注册自定义编辑器(仅登记,暂不参与编辑流程) void
unregisterCellEditor(type) 注销编辑器 void
getRegisteredCellEditor(type) 查询某 type 已注册的编辑器 CellEditorImpl \| null
usePlugin(plugin) 注册引擎插件(类或实例,引擎未就绪时自动缓冲) void

性能与调试(6)

方法 说明 返回
debug() 一帧快照:帧耗时 / 可见范围 / 滚动条矩形 TableDebugInfo \| null
startProfiler(frames?) 开启滚动帧率采样 void
stopProfiler() 关闭帧率采样 void
enableFastScroll() 开启快滚降级 void
disableFastScroll() 关闭快滚降级 void
toggleFastScroll() 切换快滚降级 void

常用写法:

const t = tableRef.value

t?.resize()                       // 容器尺寸变了
t?.scrollToIndex(200)             // 滚到第 200 行
t?.setFilters({ dept: '研发部' })  // 设筛选(null / {} = 清空)
t?.beginEditCell(0, 1)            // 进入编辑(行下标, 列下标)
t?.exportCsv()                    // 导出 CSV 字符串

TypeScript 下建议给 ref 标上实例类型(省得手写一长串签名):

import type { TableInstance } from '@/uni_modules/lime-table-x'
const tableRef = ref<TableInstance | null>(null)

类型定义

ColumnDefine(列定义)

columns 数组的每一项,也是 children 递归的类型。

字段 类型 说明
field string 数据字段名,支持 'a.b.c' 路径
key string 列标识,默认等于 field
title string 表头文案
width number 列宽(px),默认 120;总宽不足视口时按比例拉伸
minWidth number 最小列宽(px),拖拽与自适应都不会越过
maxWidth number 最大列宽(px)
align AlignType 单元格水平对齐:left / center / right
headerAlign AlignType 表头对齐,默认 center
fixed 'left' \| 'right' 固定列
sortable boolean 是否可排序
sorter (a, b) => number 自定义排序函数
filterMethod FilterMethod 列级自定义筛选匹配,优先于表级 filterMethod
resizable boolean 是否可拖拽改宽(表格 colResizable 开启时才有意义)
visible boolean 是否显示(false = 初始隐藏)
cellOverflow OverflowType 文本溢出策略:ellipsis / wrap / clip
maxLines number wrap 模式下的最大行数
tooltip boolean 溢出时显示浮层提示(需引入 tooltip 插件)
type string 内置单元格类型:image = 图片列;不填 = 文本
formatter (value, row, rowIndex) => string 文本格式化
render (params) => void 自定义绘制(函数式,禁止返回 VNode)
cellStyle CellStyleResolver 条件格式:函数式,返回 null 表示不覆盖
conditional ConditionalRule[] 条件格式:声明式规则,按顺序取首个命中
footer FooterDef 页脚汇总口径(全表)
aggregate FooterDef 组头聚合口径(组内),与 footer 独立
span SpanDef \| (row, i) => SpanDef \| null 合并单元格
editable boolean 是否可编辑:不填跟随表格 editable,false = 强制只读
editType 'text' \| 'number' \| 'textarea' 行内编辑器类型,默认 text
validators ValidatorRule[] 校验规则,提交时逐条校验
children ColumnDefine[] 多级表头子列

TreeConfig(树形配置)

字段 类型 说明
childrenKey string 子节点字段名
hasChildrenKey string 「是否有子节点」的字段名(懒加载时用)
indent number 缩进(px),默认取表格 indent
defaultExpandAll boolean 默认全部展开
lazy boolean 懒加载开关
load (row) => Promise<any[]> 加载子节点

GroupConfig(分组配置)

字段 类型 说明
field string 分组字段(支持 'a.b.c' 路径),组头显示该值
order 'asc' \| 'desc' \| 'none' 组间顺序,不填 = 按首次出现顺序
defaultExpanded boolean 初始是否展开,默认 true(受控 groupExpandedKeys 优先)
headerHeight number 组头行高(px),不填 = 与普通行同高
showCount boolean 组头是否附带行数,默认 true

FooterDef(汇总 / 聚合口径)

footer 与 aggregate 共用这一结构。

字段 类型 说明
type 'sum' \| 'avg' \| 'count' \| 'min' \| 'max' \| 'custom' \| 'text' 汇总口径
text string type: 'text' 时的固定文案
fn (values, rows) => string type: 'custom' 时的自定义计算

SpanDef

合并单元格的描述对象。

字段 / 方法 类型 说明
rowspan number 跨行数
colspan number 跨列数

ConditionalRule

声明式条件格式的一条规则。

字段 / 方法 类型 说明
when (value, row, rowIndex) => boolean 命中条件
style CellStyleRule 命中后的样式覆盖

ValidatorRule

行内编辑的校验规则。

字段 / 方法 类型 说明
type ValidatorType required / min / max / regex / custom
value number min / max 的阈值
pattern string \| RegExp regex 模式的正则
validator (value, row, i) => boolean custom 规则的判定,返回 false 即不合法
message string 自定义报错文案,缺省用内置中文文案

CellInfo

点击类事件回传的单元格信息。

字段 / 方法 类型 说明
rowIndex / colIndex number 行、列下标
field / key string 列字段名 / 列标识
value / row / rowKey any 单元格值、整行对象、行主键
column ColumnNode 列节点
rect Rect 单元格在视口内的矩形
area 'header' \| 'body' \| 'footer' 落点所在区域

CellRenderParams

render(params) 收到的上下文与绘制原语。

字段 / 方法 类型 说明
ctx / paint / theme any 底层上下文与绘制器(一般用下面的原语即可)
value / row / rowIndex any 当前单元格的值、整行、行下标
column / colIndex / rect any 列节点、列下标、单元格矩形
selected / hovered boolean 当前单元格是否被选中 / 悬浮
drawText(text, x, y, maxWidth, color?, align?) void 画文本
drawRect / drawRoundRect / drawCircle void 矩形 / 圆角矩形 / 圆
drawPolyline(points, color, lineWidth?) void 折线(sparkline)
drawSmoothLine(points, color, lineWidth?) void 平滑曲线
drawArea(points, baseY, color, alpha?) void 面积图
registerClickArea(rect, handler) void 登记可点击热区

主题定制

组件通过 props 定制主题,无需额外 CSS 变量。

方式一:暗色主题(推荐)

<l-table-x :data="data" :columns="columns" :dark="true" />

方式二:自定义色板

<l-table-x :data="data" :columns="columns" :theme="myTheme" />
// 覆盖部分色板字段(只写要改的,未写的取当前 dark 模式的默认值)
const myTheme = { textColor: '#333', borderColor: '#e5e6eb', selectedColor: '#e8f0fe' }

⚠️ 选中底色是 selectedColor(不是 selectedBgColor),选中文字色是 selectedTextColor。 mergeTheme() 只认同名字段,拼错等于没写,且不会有任何提示。可覆盖字段共 37 个,下表的后两列是内置浅色 / 暗色默认值(暗色下只写要改的字段,其余取暗色默认)。

字段 说明 浅色默认 暗色默认
backgroundColor 表格底色 '#ffffff' '#1b1f24'
borderColor 网格线 / 外框色 '#e6e8eb' '#2b323b'
borderWidth 网格线宽度(px,0 = 不画) 1 1
headerBackgroundColor 表头底色 '#f5f7fa' '#232a33'
headerTextColor 表头文字色 '#303133' '#e6edf5'
headerFontSize 表头字号(px) 14 14
headerFontWeight 表头字重(字符串,如 '600') '600' '600'
footerBackgroundColor 页脚底色 '#f5f7fa' '#232a33'
footerTextColor 页脚文字色 '#303133' '#e6edf5'
textColor 单元格文字色 '#3f4a56' '#c9d4e0'
fontSize 单元格字号(px) 14 14
fontFamily 字体族 'sans-serif' 'sans-serif'
rowBackgroundColor 行底色 '#ffffff' '#1b1f24'
stripeColor 斑马纹底色 '#fafbfc' '#1f242b'
hoverColor 悬浮行底色 '#eef6ff' '#26303c'
selectedColor 选中行 / 单元格底色 '#e3f0ff' '#24384f'
selectedTextColor 选中行文字色 '#1a6dd8' '#6cb1ff'
treeIndentColor 树形缩进引导线色 '#98a2b3' '#5d6875'
shadowColor 固定列 / 冻结行投影色 'rgba(0, 0, 0, 0.12)' 'rgba(0, 0, 0, 0.45)'
emptyTextColor 空数据 / 占位文案色 '#9aa5b1' '#5d6875'
loadingMaskColor 加载遮罩色 'rgba(255, 255, 255, 0.6)' 'rgba(27, 31, 36, 0.6)'
cellPadding 单元格左右内边距(px) 10 10
checkboxSize 复选框边长(px) 16 16
checkboxActiveColor 复选框选中色 '#2f7ef7' '#3b8ef0'
selectionFill 框选矩形填充色 'rgba(47, 126, 247, 0.12)' 'rgba(59, 142, 240, 0.22)'
activeBorder 激活格边框色 '#2f7ef7' '#3b8ef0'
findFill 查找命中填充色 'rgba(245, 158, 11, 0.24)' 'rgba(245, 158, 11, 0.28)'
findBorder 查找命中边框色 '#f59e0b' '#f0a52a'
reorderHintBg 拖拽重排:悬停提示底(半透明) 'rgba(47, 126, 247, 0.08)' 'rgba(59, 142, 240, 0.14)'
reorderActiveBg 拖拽重排:抓取态底(半透明,深于 hint) 'rgba(47, 126, 247, 0.20)' 'rgba(59, 142, 240, 0.30)'
reorderAccent 拖拽重排:强调条 / 抓手图标 '#2f7ef7' '#3b8ef0'
groupBackgroundColor 分组组头底色 '#eef2f7' '#252d37'
groupTextColor 分组组头文字色 '#303133' '#e6edf5'
groupAggregateTextColor 组头聚合值文字色(比组名浅一档) '#4a5568' '#93a2b3'
errorBackgroundColor 校验错误单元格底色 '#fef0f0' '#3a2326'
errorBorderColor 校验错误单元格边框色 '#f56c6c' '#f56c6c'
errorTextColor 校验错误单元格文字色 '#f56c6c' '#f9a3a3'

⚠️ 重要提示

关于组件使用

  • 对外只有一个业务组件 <l-table-x>。components/lime-table-x/(含 lime-table-x.uvue)是示例演示页面,内置写死的演示数据与画廊,业务代码请勿使用。
  • 尺寸请用 width / height 控制:支持数字(px)或百分比字符串(如 '100%')。不要依赖外部 class / style 去改变内部 Canvas 的绘制尺寸。
  • exportImage() 只生成不落盘:返回值格式随运行环境而定,是否存相册 / 上传 / 预览由调用方按实际返回值自行处理。
  • 行内编辑需两端齐备:组件上传 editable,且目标列未被 editable: false 置灰。
  • 包里只有壳层 + 压缩产物:引擎(core/*.ts)属于源码,不随包发布,包内是 core.esm.min.js 与自包含的 core.esm.min.d.ts。

快速预览

导入插件后,可以直接使用以下标签查看完整功能演示(含基础性能、树形、分组、编辑、导出等分类画廊):

<!-- 代码位于 uni_modules/lime-table-x/components/lime-table-x -->
<lime-table-x />

插件标签说明

标签类型 示例 说明
组件标签 l-table-x 表格核心业务组件,项目里请使用它
演示标签 lime-table-x 演示组件,用于查看完整功能演示(含示例数据,勿用于业务)

注意事项

  1. 组件初始化时需要获取 Canvas 的真实尺寸,请确保容器已具备有效宽高后再渲染。
  2. rowKey 默认 'id',若业务主键字段不同请显式设置,否则选择 / 编辑 / 展开态会错乱。
  3. 自定义单元格 render 为函数式绘制,禁止返回 VNode / 组件,只能调用注入的绘制 API。
  4. 浅色 / 暗色通过 dark 切换,theme 仅做色板覆盖,二者独立。
  5. 树形 / 分组 tree 与 groupBy 同时给时 树形优先。

常见问题

在弹窗(Popup / Dialog)中使用时组件无法正常显示?

组件初始化时需要获取 Canvas 的真实尺寸,如果弹窗尚未展开就渲染组件,Canvas 可能获取到 0 尺寸导致绘制异常。请确保弹窗展开后再渲染组件:

<l-popup v-model="show">
    <l-table-x v-if="show" :data="data" :columns="columns" />
</l-popup>

也可以使用 nextTick 延迟渲染:

const mounted = ref(false)
watch(() => show, (v) => {
    if (v) nextTick(() => { mounted.value = true })
    else mounted.value = false
})

改了 prop 没反应?

  • 组件按引用比较 data / columns:原地修改数组(data.value.push(...))不会被识别,请整体替换,或调 updateData() / updateColumns()。
  • 引擎是预打包产物,升级插件后请重新编译,H5 端可能是缓存没刷。

容器宽度变了但表格没跟着变?

组件只在自身尺寸变化时自动重排。外层布局变化但组件本身尺寸未变(如侧栏收起导致父容器重新分配)时,请手动调 tableRef.value?.resize()。

支持与赞赏

如果你觉得本插件解决了你的问题,可以考虑支持作者:

支付宝赞助 微信赞助

隐私、权限声明

1. 本插件需要申请的系统权限列表:

无

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

无

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

暂无用户评论。