Trae教你实现Canvas 表格,提高渲染性能

前言

你是否只会使用element、antd等组件库的表格?你是否只会谴责后端返回的数据很多,导致你的页面卡爆,卡成ppt,用户体验下降?你是否会因为数据量太大,导致页面卡顿,用户体验下降?虚拟列表,你是不是经常听到定高的列表,不定高的虚拟列表,这是不是听起来很懵逼,那么你是不是以为我会讲虚拟列表?

不,我今天不讲虚拟列表,今天我来讲canvas实现一个高性能的table,再也不担心后端返回大量数据,导致前端的页面卡顿,用户体验下降。

依旧是我们的Trae ai,先简单的提问,让Trae模拟大量的数据,这样就不用我们手动添加了,偷个懒吧,啊哈哈哈

看看最终的样式效果,滚动起来,一点都不卡顿,很丝滑

Trae的实现思路

一、Trae设计的思路

  • 目标:在普通浏览器环境中流畅渲染 10 万+ 行表格,滚动不卡顿。
  • 核心策略:Canvas 即时渲染 + 虚拟滚动。只绘制"可视区域内"的行,不创建海量 DOM 节点。
  • 关键优化:
    • 高 DPI 适配:一次性 setTransform(dpr, 0, 0, dpr, 0, 0) 消除模糊。
    • 预计算列几何:列累计偏移 colX[] 只算一次,循环直接查表。
    • requestAnimationFrame 合帧:滚动时只在下一帧绘制,避免重复触发。
    • 数据"按需生成":通过行号生成数据,不在内存里存放 10 万对象。

二、数据与内存策略

  • 不真正"持有"数据数组,而是利用行号 i 通过一个轻量的伪随机函数生成可复现的数据。这样总内存占用基本与总行数无关,只有可见行的文本参与绘制。
  • 优点:零初始化成本、零大对象分配、滚动时无需数据搬运。

Trae的实现代码

预计算列位置,避免重复相加成本

js 复制代码
  const colX = new Array(COLS.length + 1);
  function computeColX() {
    colX[0] = 0;
    for (let i = 0; i < COLS.length; i++) colX[i + 1] = colX[i] + COLS[i];
  }
  computeColX();

用行号 i 生成稳定的"随机"数据,避免存储大数组

js 复制代码
function rand(i){ const x = Math.sin(i * 9999) * 10000; return x - Math.floor(x); }
function rowData(i){
  const n = i + 1;
  const age = 18 + Math.floor(rand(n)*40);
  const score = (rand(n*3)*100).toFixed(2);
  const level = ['Bronze','Silver','Gold','Platinum','Diamond'][Math.floor(rand(n*7)*5)];
  const status = rand(n*11) > 0.5 ? '正常' : '冻结';
  const city = ['上海','北京','深圳','杭州','成都','武汉','西安','广州'][Math.floor(rand(n*5)*8)];
  const time = new Date(1600000000000 + Math.floor(rand(n*13)*1e10)).toISOString().slice(0,19).replace('T',' ');
  return [n, '用户'+n, city, age, score, level, status, time, 'OD'+(100000+n), '---'];
}

关键的虚拟滚动实现

js 复制代码
const firstRow = Math.max(0, Math.floor((viewTop - HEADER_H) / ROW_H));
const visibleCount = Math.ceil(h / ROW_H) + 1;
const lastRow = Math.min(TOTAL_ROWS, firstRow + visibleCount);
let y = HEADER_H - ((viewTop - HEADER_H) % ROW_H);

高 DPI 渲染适配

js 复制代码
const dpr = Math.max(1, Math.floor(window.devicePixelRatio || 1));
canvas.width = w * dpr; canvas.height = h * dpr;
ctx.setTransform(dpr, 0, 0, dpr, 0, 0); // 只设置一次

总结

虚拟滚动是一种优化长列表渲染的技术,通过只渲染可视区域内的元素,大幅减少 DOM 操作和重绘,提高性能。

本文介绍了canvas表格虚拟滚动的原理和实现,包括如何计算可视区域、如何渲染数据、如何处理滚动事件等。通过虚拟滚动,我们可以轻松处理百万级的数据,实现流畅的滚动效果。

如果你之前没有接触过虚拟滚动,希望本文能帮你入门。如果你已经熟悉虚拟滚动,希望本文能帮你优化你的实现。

相关推荐
用户40993225021213 分钟前
Vue3条件渲染中v-if系列指令如何合理使用与规避错误?
前端·ai编程·trae
早川不爱吃香菜8 小时前
MCP 教程:使用高德地图 MCP Server 规划行程
mcp·trae
早川不爱吃香菜1 天前
8 个支持一键导入 TRAE 使用的自定义智能体
trae
用户4099322502121 天前
Vue3动态样式控制:ref、reactive、watch与computed的应用场景与区别是什么?
后端·ai编程·trae
前端无涯2 天前
Trae的使用
前端·ide·trae
用户4099322502122 天前
Vue3动态样式管理:如何混合class/style绑定、穿透scoped并优化性能?
前端·ai编程·trae
飞哥数智坊2 天前
TRAE 内 GPT-5.2 实测:10 轮对话,生成的代码一次都没让我撤回
人工智能·gpt·trae
用户4099322502123 天前
Vue3中动态样式数组的后项覆盖规则如何与计算属性结合实现复杂状态样式管理?
前端·ai编程·trae
五号厂房3 天前
Trae + Spec:AI帮你手搓代码的神仙组合,太上头了!
trae
围巾哥萧尘3 天前
🚀TRAE SOLO 实战赛 | 智启Coding 码力全开 | 在TRAE SOLO中使用PyeChart创建一个HTML格式的子母饼图网站🧣
trae