当前位置: 首页 > ai >正文

页面实现渲染大量 DOM 元素

页面实现渲染大量 DOM 元素

一、使用 setTimeout 进行分批渲染

1.1、实现方案

function process() {for (let i = 0; i < batchSize; i++) {if (processed >= total) return;const div = document.createElement('div');...fatherDom.appendChild(div);processed++;};if (processed < total) {setTimeout(process, 0);}
}

1.2、原理解析

  • setTimeout(fn, 0) 并不是“立即执行”,而是将 fn 推到宏任务队列中,等待当前执行栈清空后再执行。
  • 每次执行只插入 batchSize 个元素,然后将“下一批任务”再次放到事件循环中,以避免主线程被长时间阻塞。
  • 浏览器有机会在任务之间处理用户输入、重绘等操作,提升响应性。

1.3、优点

  • 相对简单。

  • 在旧浏览器中也能良好工作。

1.4、缺点

  • 不精确:setTimeout 受浏览器调度器控制,延迟时间不确定。

  • 宏任务调度会占用较多主线程时间,导致页面流畅性和用户交互能力下降。

  • 页面滚动/动画可能变卡。

二、使用 requestAnimationFrame 进行分批渲染

2.1、实现方案

function processBatch() {requestAnimationFrame(() => {for (let i = 0; i < batchSize; i++) {if (processed >= total) return;const div = document.createElement('div');...fatherDom.appendChild(div);processed++;}if (processed < total) {processBatch();}});
}

2.2、原理解析

requestAnimationFrame(fn) 是浏览器专门为动画或逐帧任务设计的接口:

  • 回调 fn 会在 下一帧绘制之前 执行。
  • 浏览器通常以 60 FPS 为目标(即每 16.67ms 调用一次回调)。
  • 它是一个 微任务与宏任务之间的“帧任务”调度机制,更适合用于逐帧渲染或分批插入 DOM。

2.3、优点

  • 更平滑:浏览器知道你要进行渲染操作,会自动协调布局和绘制的时机。
  • 不会阻塞 UI 渲染,可保持高帧率和良好响应性。
  • 性能更高效,尤其适合动画、渲染大量内容等任务。

2.4、缺点

  • 每帧执行次数有限,不适合一次性添加太多元素
  • 如果 batchSize 设置过大,还是会卡顿

三、虚拟列表 / 虚拟滚动(Virtual Scrolling)

3.1、🧠 原理概述

虚拟列表是一种按需渲染技术。你只渲染当前屏幕中可见的元素,其他元素并不会真实存在于 DOM 中。这样即使你有 100 万个数据项,页面中也只存在几十甚至更少的 DOM 节点

3.2、✅ 核心优点

  • 实际 DOM 数量小(几十个),性能极高;

  • 滚动平滑,不会出现卡顿;

  • 适合超大数据量列表(10万~1000万);

  • 可和分页、异步加载等策略结合

3.3 ✅ 推荐实现方式

✅ 方式一:使用成熟库(强烈推荐)

👉 React-Virtualized

  • React 专用,功能丰富、性能强悍。
  • 支持表格、列表、瀑布流等。

👉 Vue-Virtual-Scroller

  • Vue 专用。
  • 支持动态高度、平滑滚动等。

👉 Clusterize.js(适合原生 JS)

  • 纯原生 JS 实现,适合不使用框架的场景;
  • 易集成,超轻量(< 5KB)

✅ 方式二:手动实现一个简单虚拟列表(原生 JS-示意)

<style>.viewport {height: 500px;overflow-y: scroll;border: 1px solid #ccc;position: relative;}.spacer {height: 2000000px; /* 假设一百万个,每个20px */}.item {position: absolute;height: 20px;line-height: 20px;width: 100%;padding-left: 1rem;box-sizing: border-box;}
</style><div class="viewport" id="viewport"><div class="spacer" id="spacer"></div>
</div><script>const viewport = document.getElementById("viewport");const spacer = document.getElementById("spacer");const itemHeight = 20;const totalItems = 1000000;const visibleCount = Math.ceil(viewport.clientHeight / itemHeight) + 10;const pool = [];for (let i = 0; i < visibleCount; i++) {const div = document.createElement("div");div.className = "item";viewport.appendChild(div);pool.push(div);}function render() {const scrollTop = viewport.scrollTop;const start = Math.floor(scrollTop / itemHeight);for (let i = 0; i < pool.length; i++) {const index = start + i;if (index >= totalItems) {pool[i].style.display = "none";} else {pool[i].style.display = "block";pool[i].style.top = (index * itemHeight) + "px";pool[i].textContent = `这是第 ${index + 1}`;}}}viewport.addEventListener("scroll", render);render(); // 初始渲染
</script>

四、🧠 总结:几种方案对比

方案渲染性能用户体验DOM 数量优点缺点
setTimeout 分批渲染中等容易卡顿实现简单容易丢帧,主线程阻塞
requestAnimationFrame较好比较平滑更流畅DOM 太多仍然卡
虚拟滚动非常好极为流畅极低性能极佳,真实可用实现稍复杂,需要计算映射关系
Web Worker + Canvas非常好非 DOM 场景0可视化强,不卡顿只能用于图形渲染,非 DOM 操作

五、❓适用建议

  • ✅ 要处理百万数据项,强烈推荐虚拟滚动;
  • ❌ 不要直接往页面插入 100 万个 DOM 元素;
  • 🧪 想测试浏览器性能,可以用分批方式;
  • 🎨 如果要进行图形展示,如地理数据、节点图,考虑使用 Canvas/WebGL(如 D3.js, Pixi.js, Cesium)
http://www.xdnf.cn/news/8643.html

相关文章:

  • 哈希表-有效的数字异位词
  • 基于大模型的短暂性脑缺血发作预测与干预全流程系统技术方案大纲
  • 使用Collections.unmodifiableX()构建只读集合,保护你的数据不被修改!
  • C++----Vector的模拟实现
  • vue3+ts 安装tailwindcss样式库
  • 2025年上半年软件架构师考试回忆版【持续更新】
  • AI开发 | Web API框架选型-FastAPI
  • AtCoder AT_abc407_c [ABC407C] Security 2
  • 抖音出品AI短剧《牧野诡事》能否给AI短剧带来新一轮爆发?
  • Arduino和STM32的区别详解
  • 编译rk3568的buildroot不起作用
  • Linux概述
  • QGIS新手教程:两种方法创建点图层(手动添加 + 表格导入),支持经纬度定位与查找
  • C++类和对象-1
  • Qwen2.5 VL 语言生成阶段(4)
  • 【MPC控制 - 从ACC到自动驾驶】1 ACC系统原理与MPC初步认知
  • 力扣刷题Day 53:和为 K 的子数组(560)
  • WHAT - 兆比特每秒 vs 兆字节每秒
  • 处理三高业务
  • 趋势触发策略
  • 第四十九节:图像分割-基于深度学习的图像分割
  • 国际前沿知识系列四:格兰杰因果分析在脑区应变原因分析中的应用
  • 深入理解API:从概念到实战
  • leetcode 两数相加 java
  • 51页 @《人工智能生命体 新启点》中國龍 原创连载
  • redis的AOF恢复数据
  • CMake基础:CMakeLists.txt 文件结构和语法
  • github公开项目爬取
  • SMT贴片机操作核心步骤精要
  • 在kali中搞个jdk1.8.,又不破坏环境