@silly_yi/easytable
v0.2.1
Published
Canvas-based virtualized table for huge datasets
Readme
@silly_yi/easytable
一个基于 Canvas 的虚拟化表格,面向大数据量(十万/百万行)场景:滚动、选区、复制、编辑、排序、筛选、固定列、合并单元格、图片单元格等都在 Canvas 上完成渲染。
特性
- Canvas 渲染,DOM 节点极少,适合大数据量
- 虚拟滚动(按视口渲染行/列),滚动流畅
- 表头排序(支持自定义 sortValue/comparator)
- 表头筛选面板(列表/文本两种模式,支持超大列表虚拟化)
- Excel 风格选区与复制(Ctrl/Cmd+C)
- 单元格编辑(可配合数据源写回)
- 列宽拖拽、固定列(left)、合并单元格、图片单元格
安装
npm i @silly_yi/easytable快速开始(数组数据)
import { EasyTable } from "@silly_yi/easytable";
const container = document.getElementById("table")!;
const rows = Array.from({ length: 10000 }).map((_, i) => ({
id: i + 1,
name: `User ${i + 1}`,
email: `user${i + 1}@example.com`,
}));
const table = new EasyTable(container, {
data: rows,
rowHeight: 32,
headerHeight: 40,
enableEditing: true,
enableSelection: true,
enableClipboard: true,
enableFiltering: true,
enableSorting: true,
enableColumnResize: true,
columns: [
{ key: "id", title: "ID", width: 80, fixed: "left", sortable: true },
{ key: "name", title: "姓名", width: 160, sortable: true, editable: true },
{ key: "email", title: "邮箱", width: 260, editable: true, filterable: true },
],
onCellChange: (e) => {
console.log("cell change:", e.row, e.col, e.oldValue, "->", e.newValue);
},
});大数据推荐(getRow 懒数据源)
当数据量很大时,不建议一次性构建巨大数组;推荐使用 rowCount + getRow 方式按需生成行数据。
import { EasyTable } from "@silly_yi/easytable";
const ROWS = 300000;
const COLUMNS = 30;
const overrides = new Map<number, any>();
const data = {
rowCount: ROWS,
getRow: (i: number) => {
const override = overrides.get(i);
if (override) return override;
const row: any = { id: i + 1 };
for (let c = 1; c < COLUMNS; c++) row[`c${c}`] = `R${i + 1}-C${c}`;
return row;
},
setCell: (i: number, key: string, value: unknown) => {
const base = overrides.get(i) ?? data.getRow(i);
overrides.set(i, { ...base, [key]: value });
},
};
new EasyTable("#table", {
data,
rowHeight: 32,
headerHeight: 40,
enableEditing: true,
columns: Array.from({ length: COLUMNS }).map((_, i) => ({
key: i === 0 ? "id" : `c${i}`,
title: i === 0 ? "ID" : `列${i}`,
width: i === 0 ? 80 : 120,
sortable: true,
editable: true,
fixed: i < 2 ? "left" : undefined,
})),
});排序说明
- 数组数据(
EasyTableRow[]或{ rows })会在组件内部排序。 getRow数据源优先走你提供的data.sort(state) => number[](例如走服务端排序)。- 如果
getRow未提供sort,组件会在前端以异步分片方式构建排序索引并刷新表格(适合中等规模;超大规模建议使用服务端/预索引)。
筛选说明
- 点击表头漏斗图标打开筛选面板。
- 列表模式下,选项采用虚拟列表,只渲染固定数量 DOM。
- 在搜索框输入关键字后,会异步扫描并显示匹配项;同时会把匹配项全部选中、未匹配项取消选中;点击“确定”应用筛选。
API 概览
构造与方法
new EasyTable(container, options)setData(data)updateOptions(partialOptions)resize()destroy()scrollToRow(rowIndex)scrollToCell(rowIndex, colIndex)downloadCSV(filename, { range: "selection" | "all" })
Options(常用)
data:支持三种形态:EasyTableRow[]/{ rows }/{ rowCount, getRow, setCell?, setRow?, sort? }columns:列配置(key/title/width/fixed/type/sortable/filterable/resizable/editable/...)rowHeight、headerHeight、font、headerFontenableSelection、enableClipboard、enableSorting、enableEditing、enableColumnResize、enableFilteringtheme、cells、merges、cellStyle- 回调:
onCellClick/onCellChange/onColumnResize/onFilterChange/...
更完整的类型定义在 types.ts。
开发与构建
npm run typecheck
npm run build本仓库内置了一个 index.html 演示页,可直接用静态服务器打开:
python -m http.server 3000然后访问:http://localhost:3000/index.html
License
MIT
