前端性能救星!用 requestAnimationFrame 丝滑渲染海量数据

大家好,我是江城开朗的豌豆,一名拥有6年以上前端开发经验的工程师。我精通HTML、CSS、JavaScript等基础前端技术,并深入掌握Vue、React、Uniapp、Flutter等主流框架,能够高效解决各类前端开发问题。在我的技术栈中,除了常见的前端开发技术,我还擅长3D开发,熟练使用Three.js进行3D图形绘制,并在虚拟现实与数字孪生技术上积累了丰富的经验,特别是在虚幻引擎开发方面,有着深入的理解和实践。

我一直认为技术的不断探索和实践是进步的源泉,近年来,我深入研究大数据算法的应用与发展,尤其在数据可视化和交互体验方面,取得了显著的成果。我也注重与团队的合作,能够有效地推动项目的进展和优化开发流程。现在,我担任全栈工程师,拥有CSDN博客专家认证及阿里云专家博主称号,希望通过分享我的技术心得与经验,帮助更多人提升自己的技术水平,成为更优秀的开发者。

技术qq交流群:906392632

大家好,我是小杨,一个做了6年前端的老司机。今天想和大家聊聊一个常见但头疼的问题:如何在不卡死页面的情况下渲染大量数据?

不知道你有没有遇到过这样的场景:后端一次性返回几万条数据,前端直接 forEach + appendChild 暴力渲染,结果页面直接卡死,用户疯狂投诉......(别问我怎么知道的 😅)

其实,解决这个问题并不难,关键在于分批渲染 ,而 requestAnimationFrame(简称 rAF)就是我们的最佳帮手!


1. 为什么直接渲染大数据会卡?

假设我们有 10,000 条数据,如果一次性全部塞进 DOM:

javascript 复制代码
const data = Array(10000).fill("我是数据项");  
const container = document.getElementById('list');  

data.forEach(item => {
  const div = document.createElement('div');
  div.textContent = item;
  container.appendChild(div);
});

问题来了:

  • JS 执行阻塞:一次性创建 10,000 个 DOM 节点,JS 引擎会卡住主线程。
  • 渲染延迟:浏览器需要处理大量 DOM 插入,导致页面冻结,用户无法交互。
  • 内存占用高:大量 DOM 节点堆积,内存飙升,甚至可能崩溃。

结论: 不能一次性渲染所有数据!


2. 解决方案:分批渲染 + requestAnimationFrame

requestAnimationFrame 是浏览器提供的 API,它会在下一次重绘之前 执行回调,通常是 16.6ms(60FPS) 执行一次,这样可以让渲染更流畅。

优化思路:

  1. 分批次渲染:每次只渲染一小部分数据(比如 50 条)。
  2. 利用 rAF 控制渲染时机,避免阻塞主线程。
  3. 滚动加载优化 (可选):结合 IntersectionObserver 实现懒加载。

代码实现:

javascript 复制代码
function renderLargeData(data, chunkSize = 50) {
  const container = document.getElementById('list');
  let index = 0;

  function renderChunk() {
    // 每次渲染 chunkSize 条数据
    const chunkEnd = Math.min(index + chunkSize, data.length);
    
    for (; index < chunkEnd; index++) {
      const div = document.createElement('div');
      div.textContent = 我是.data[index];
      container.appendChild(div);
    }

    // 如果还有数据,继续渲染
    if (index < data.length) {
      requestAnimationFrame(renderChunk);
    }
  }

  // 开始渲染
  renderChunk();
}

// 测试
const bigData = Array(10000).fill("我是数据项");
renderLargeData(bigData);

优化效果:

页面不卡顿 :每次只渲染少量 DOM,主线程不会被阻塞。

流畅渲染rAF 确保在浏览器空闲时执行,不影响用户交互。

内存可控:不会一次性创建大量 DOM,减少内存压力。


3. 进阶优化:虚拟滚动(Virtual Scroll)

如果你的数据量真的超级大(比如 10W+),即使分批渲染也会占用大量 DOM,这时可以考虑 虚拟滚动(只渲染可视区域内的元素)。

核心思路:

  • 只渲染可见区域的数据,滚动时动态替换内容。
  • 使用 IntersectionObserver 或监听 scroll 事件计算可视范围。
javascript 复制代码
// 简单示例(完整实现会更复杂)
function renderVirtualScroll(data, container, itemHeight = 50) {
  const viewportHeight = container.clientHeight;
  const visibleItemCount = Math.ceil(viewportHeight / itemHeight);
  let startIndex = 0;

  function updateVisibleItems() {
    const endIndex = startIndex + visibleItemCount;
    const visibleData = data.slice(startIndex, endIndex);

    container.innerHTML = '';
    visibleData.forEach(item => {
      const div = document.createElement('div');
      div.style.height = `${itemHeight}px`;
      div.textContent = 我是.item;
      container.appendChild(div);
    });
  }

  container.addEventListener('scroll', () => {
    startIndex = Math.floor(container.scrollTop / itemHeight);
    updateVisibleItems();
  });

  updateVisibleItems();
}

适用场景:

📌 超长列表(如聊天记录、日志数据)

📌 表格数据渲染

📌 无限滚动(Infinite Scroll)


4. 总结:如何选择优化方案?

方案 适用场景 优点 缺点
分批渲染(rAF 数据量中等(1k~10k) 实现简单,兼容性好 DOM 节点仍较多
虚拟滚动 数据量超大(10k+) 极致性能,内存占用低 实现较复杂

我的建议:

  • 如果数据量 < 5000,直接渲染问题不大。
  • 如果数据量 5000~10W ,用 requestAnimationFrame 分批渲染。
  • 如果数据量 > 10W,考虑虚拟滚动或后端分页。

5. 最后的小技巧

  • setTimeout vs rAFrAFsetTimeout 更适合动画/渲染,因为它与浏览器刷新率同步。
  • Web Worker:如果数据处理很耗时(如排序、过滤),可以丢给 Web Worker,避免阻塞 UI。
  • 分页加载:如果可能,尽量让后端分页,减少前端压力。

结语

渲染大数据并不可怕,关键是要避免阻塞主线程requestAnimationFrame 是一个强大的工具,合理使用能让你的页面丝滑流畅!

相关推荐
lyj16899715 分钟前
vue-i18n+vscode+vue 多语言使用
前端·vue.js·vscode
小白变怪兽2 小时前
一、react18+项目初始化(vite)
前端·react.js
ai小鬼头2 小时前
AIStarter如何快速部署Stable Diffusion?**新手也能轻松上手的AI绘图
前端·后端·github
墨菲安全3 小时前
NPM组件 betsson 等窃取主机敏感信息
前端·npm·node.js·软件供应链安全·主机信息窃取·npm组件投毒
GISer_Jing3 小时前
Monorepo+Pnpm+Turborepo
前端·javascript·ecmascript
天涯学馆3 小时前
前端开发也能用 WebAssembly?这些场景超实用!
前端·javascript·面试
我在北京coding4 小时前
TypeError: Cannot read properties of undefined (reading ‘queryComponents‘)
前端·javascript·vue.js
前端开发与ui设计的老司机4 小时前
UI前端与数字孪生结合实践探索:智慧物流的货物追踪与配送优化
前端·ui
全能打工人4 小时前
前端查询条件加密传输方案(SM2加解密)
前端·sm2前端加密