canvas-table-kit
v0.1.3
Published
High-performance Canvas table with 3-tier rendering (Canvas/Tile/Skia WASM), supporting 100k-10M+ rows, Vanilla JS / React / Vue 3
Maintainers
Readme
canvas-table-kit
基于 Canvas 的高性能表格组件,采用三级渲染架构,支持 10 万 ~ 1000 万+ 行数据流畅渲染。核心引擎与框架无关,提供 原生 JS、React 和 Vue 3 三种适配器。
特性
- 三级渲染架构 — 按数据规模选择最佳渲染后端:
- 一级 · Canvas 直绘 — ~10 万行,零依赖
- 二级 · Canvas + 瓦片 — ~100 万行,LRU 缓存瓦片渲染
- 三级 · Skia + WASM — 1000 万+ 行,WebGL/WebGPU GPU 加速
- 虚拟滚动 — 仅渲染可视区域内的行和列
- 多框架适配 — 无缝集成原生 JS、React 17+、Vue 3
- TypeScript 优先 — 完整类型声明文件
- Web Worker 卸载 — 超过 5 万行数据自动在后台线程排序和搜索
- 可定制主题 — 覆盖表头、行、边框、字体等样式
- 内置交互 — 列宽调整 · 排序 · 搜索 · 单元格编辑
安装
npm install canvas-table-kit快速开始
原生 JS
import { createCanvasTable } from "canvas-table-kit";
const table = createCanvasTable(document.getElementById("mount"), {
columns: [
{ key: "id", title: "编号", width: 80 },
{ key: "name", title: "姓名", width: 200, sortable: true, editable: true },
{
key: "salary",
title: "薪资",
width: 120,
render: (v) => `¥${Number(v).toLocaleString()}`,
},
],
data: generateData(100000),
renderer: "canvas", // 'canvas' | 'tile' | 'skia'
rowHeight: 36,
headerHeight: 40,
});
// 运行时切换渲染器
table.switchRenderer("tile", { tileWidth: 512, tileHeight: 512 });
// 更新数据
table.setData(newData);
// 排序 / 搜索
table.sort("name", "asc");
table.search("张三");
// 销毁实例
table.destroy();React
import { CanvasTable } from "canvas-table-kit/react";
function App() {
return (
<CanvasTable
columns={columns}
data={data}
renderer="canvas"
rowHeight={36}
headerHeight={40}
fixedHeader
onCellClick={(cell, value) => console.log(cell, value)}
onSort={(key, dir) => console.log(key, dir)}
style={{ width: "100%", height: 500 }}
/>
);
}Vue 3
<script setup>
import { CanvasTable } from "canvas-table-kit/vue";
</script>
<template>
<CanvasTable
:columns="columns"
:data="data"
renderer="canvas"
:row-height="36"
:header-height="40"
fixed-header
@cell-click="onCellClick"
@sort="onSort"
/>
</template>API
CanvasTableOptions(配置选项)
| 属性 | 类型 | 默认值 | 说明 |
| -------------- | ------------------------------ | ---------- | ---------------------- |
| columns | Column[] | 必填 | 列定义 |
| data | Record<string, unknown>[] | 必填 | 行数据 |
| renderer | 'canvas' \| 'tile' \| 'skia' | 'canvas' | 渲染后端 |
| rowHeight | number | 32 | 行高(像素) |
| headerHeight | number | 40 | 表头高度(像素) |
| fixedHeader | boolean | false | 滚动时固定表头 |
| tile | TileConfig | — | 瓦片渲染器配置(二级) |
| skia | SkiaConfig | — | Skia WASM 配置(三级) |
| theme | Partial<ThemeConfig> | — | 主题覆盖 |
Column(列定义)
| 属性 | 类型 | 说明 |
| ----------------------- | ------------------------------- | ---------------- |
| key | string | 数据字段键 |
| title | string | 列标题文本 |
| width | number | 固定列宽 |
| minWidth / maxWidth | number | 列宽约束 |
| fixed | 'left' \| 'right' | 冻结列 |
| sortable | boolean | 启用排序 |
| editable | boolean | 启用行内编辑 |
| render | (value, row, index) => string | 自定义单元格渲染 |
| align | 'left' \| 'center' \| 'right' | 文本对齐方式 |
CanvasTableInstance(原生 JS 实例方法)
| 方法 | 说明 |
| ------------------------------- | --------------------------------------------- |
| setData(data) | 替换全部行数据 |
| updateData(data) | 合并/更新行 |
| sort(columnKey, direction) | 按列排序 |
| search(keyword) | 高亮匹配行 |
| switchRenderer(type, config?) | 运行时切换渲染后端 |
| getRendererType() | 返回当前渲染器类型 |
| getVisibleRange() | 返回 { startRow, endRow, startCol, endCol } |
| scrollTo(rowIndex) | 滚动到指定行 |
| scrollToColumn(columnKey) | 滚动到指定列 |
| destroy() | 销毁实例并清理资源 |
事件
| 事件 | 回调参数 |
| ---------------- | ------------------------------------------------------ |
| onCellClick | (cell: CellPosition, value: unknown) |
| onCellEdit | (cell: CellPosition, newVal: string, oldVal: string) |
| onSort | (columnKey: string, direction: 'asc' \| 'desc') |
| onSearch | (keyword: string, matchedIndices: number[]) |
| onColumnResize | (columnKey: string, newWidth: number) |
渲染器配置
TileConfig(二级 · 瓦片渲染)
{
tileWidth: 512, // 瓦片宽度(默认: 512)
tileHeight: 512, // 瓦片高度(默认: 512)
maxCacheSize: 200, // LRU 缓存容量(默认: 100)
overscanTiles: 1, // 视口外预渲染瓦片数(默认: 1)
}SkiaConfig(三级 · Skia WASM)
{
wasmUrl: '/wasm/skia-wasm.wasm', // WASM 二进制文件地址
gpuBackend: 'webgl', // 'webgl' | 'webgpu' | 'cpu'
sharedArrayBuffer: true, // 启用多线程
workerCount: 4, // 并行渲染的 Worker 数量
}主题定制
{
headerBg: '#1a1a2e', // 表头背景色
headerColor: '#e0e0ff', // 表头文字色
headerHeight: 40, // 表头高度
rowBg: '#16162a', // 行背景色
rowAltBg: '#1e1e3a', // 交替行背景色
rowColor: '#ccccdd', // 行文字色
selectedBg: '#2a2a5a', // 选中行背景色
fontSize: 14, // 字体大小
fontFamily: '-apple-system, BlinkMacSystemFont, sans-serif',
cellPadding: 8, // 单元格内边距
}架构
canvas-table-kit/
├── src/
│ ├── core/ → 引擎核心、布局计算、虚拟滚动、事件系统
│ ├── renderers/ → Canvas / Tile / Skia 可插拔渲染后端
│ ├── adapters/ → 原生 JS / React / Vue 框架适配桥接
│ ├── bridge/ → 浅比较、数据差异检测
│ └── workers/ → Web Worker 管理(排序 + 搜索)
├── dist/ → 构建产物 CJS + ESM + .d.ts 类型声明
└── tests/ → Vitest 单元测试(85 个用例)浏览器兼容性
| 渲染器 | Chrome | Firefox | Safari | Edge | | -------------- | -------- | -------- | ----------- | -------- | | Canvas(一级) | ✅ | ✅ | ✅ | ✅ | | Tile(二级) | ✅ | ✅ | ✅ | ✅ | | Skia(三级) | ✅ WebGL | ✅ WebGL | ⚠️ 部分支持 | ✅ WebGL |
三级渲染(Skia + WASM)的多线程功能需要 SharedArrayBuffer,请确保服务器返回以下响应头:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp许可证
MIT
