Canvas表格组件本质是将DOM节点树转为绘制指令流,通过自定义渲染器控制坐标、内容与重绘时机,基于VNode抽象Table/Row/Col/Cell节点,结合虚拟滚动、坐标映射、局部更新与dpr适配实现高性能交互。

Canvas绘制表格组件用自定义渲染器,本质是把表格从“DOM节点树”转向“绘制指令流”——不靠浏览器排版引擎,而是由你控制每一笔画在哪、画什么、何时重绘。
把表格结构转成可 diff 的 VNode
传统表格靠 HTML 标签嵌套表达行列关系,Canvas 表格需要抽象出语义化指令节点。比如:
- Table:代表画布容器,负责初始化 ctx、监听 resize、管理 viewport 尺寸
- Row / Col:不生成真实元素,只携带起始坐标、高度/宽度、是否冻结等元信息
- Cell:含 data、colSpan、rowSpan、对齐方式、背景色等 props,最终映射为 fillText + strokeRect 组合
- 所有节点带 key,确保滚动或排序时能复用绘制状态,避免全量重绘
重写核心渲染钩子,绕过 DOM 流程
Vue 或类似响应式框架的自定义渲染器需接管底层行为:
用户要生成可打印的中文字帖/练习纸、导出多页 A4 PDF 报告,或把 SVG 设计稿零误差还原到 Canvas 时使用。本技能是「Canvas 内容工厂闭环」的总控,编排:网格渲染引擎(13 种教育网格+拼音标注) → 多页 PDF 导出(A4 合成) → SVG 精准复刻(坐标误差<0.001px)。触发词:生成字帖、练习纸、导出 PDF、SVG 转 Canvas、印刷级还原、A4 报告、米字格田字格。
-
hostCreateElement:返回轻量对象,如
{ type: 'cell', props: { x: 200, y: 120, text: '张三' } } - hostPatchProp:属性变更时不操作 DOM,而是标记该 cell 为“脏区域”,下次 render 时局部重绘
- hostInsert:将 VNode 加入绘制队列,按 y 坐标排序后批量调用 ctx.fillText / ctx.strokeRect
-
hostRemove:Canvas 无法删像素,所以实际是清空对应矩形区域(
clearRect),或延迟到下一帧整体重绘
支持虚拟滚动与坐标映射
千万行表格不能靠 scrollHeight 撑开页面,必须做逻辑坐标与物理坐标的分离:
- 维护 worldTop(当前滚动到第几行)和 viewportHeight(可视行数),推算出 startRow / endRow
- 用
Math.floor(worldTop / rowHeight)确定首行索引,再循环绘制 10–20 行可见内容 - 表头固定时,单独维护一个 headerCanvas 或分层绘制:主 canvas 绘数据区,叠加 canvas 绘冻结行/列
- 鼠标事件需反向映射:clientY → worldY → 行号,依赖精确的 scale 计算,而非 event.target
兼顾交互与性能的更新策略
真正落地时,渲染器要回应真实场景需求:
- 编辑态下,点击 cell 触发
editing = { row, col },渲染器跳过该单元格文本,改画 input 框轮廓或直接委托原生 input 定位 - 悬停高亮:hoverCell 变更时,只重绘两行(原 hover 行 + 新 hover 行),不触发整表刷新
- 数据更新走 patch 而非 replace:对比新旧 data 数组,仅标记 diff 行为 “update”、“insert”、“delete”,驱动对应 cell 的局部重绘
- 启用 devicePixelRatio 缩放:canvas.width = width × dpr,ctx.scale(dpr, dpr),保证高清屏下文字清晰不模糊

















