原生JS实现虚拟列表(不使用Vue,React等前端框架)
好家伙,
1. 什么是虚拟列表
虚拟列表(Virtual List)是一种优化长列表渲染性能的技术。当我们需要展示成千上万条数据时,如果一次性将所有数据渲染到DOM中,会导致页面卡顿甚至崩溃。虚拟列表的核心思想是:只渲染可视区域内的数据,而不是渲染所有数据
2. 使用场景
虚拟列表适用于以下场景:
- 大数据量展示:如聊天记录、新闻列表、商品列表等需要展示大量数据的场景
- 无限滚动:需要支持用户持续滚动加载更多内容的场景
- 性能敏感:在低性能设备上运行的应用,需要尽可能减少DOM操作
- 实时数据更新:频繁更新的数据列表,如股票行情、实时监控数据等
(我觉得实际场景中,分页会用到更多,用户要看的数据,永远只是一小部分,就那么几条,找不到就用搜索
但总要学学)
3. 虚拟列表原理
一句话:
要看了,再渲染
对,就这么简单,下面,进行分步
- 计算可视区域:确定用户当前可以看到的视口范围
- 计算可见项:根据视口位置、每项高度,计算出当前应该显示哪些数据项
- 渲染可见项:只渲染计算出的可见项到DOM中
- 位置偏移:通过CSS定位,确保可见项在正确的位置显示
- 监听滚动:当用户滚动时,重新计算可见项并更新DOM
这里几个难点:
我怎么知道哪些数据进入了可视区域?
答:监听滚动距离,滚到哪,就从哪里开始
4. 实现虚拟列表
Demo.html代码如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>原生JavaScript虚拟列表实现</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
} .list-container {
position: relative;
height: 400px;
overflow: auto;
border: 1px solid #ccc;
margin: 20px auto;
width: 80%;
} .list-phantom {
position: absolute;
left: 0;
top: 0;
right: 0;
z-index: -1;
} .list-content {
position: absolute;
left: 0;
right: 0;
top: 0;
overflow: hidden;
} .list-item {
padding: 10px;
border-bottom: 1px solid #eee;
color: #666;
} .list-item:hover {
background-color: #f5f5f5;
}
</style>
</head>
<body>
<h1 style="text-align: center; margin: 20px 0;">原生JavaScript虚拟列表</h1>
<div id="virtualList" class="list-container">
<div class="list-phantom"></div>
<div class="list-content"></div>
</div> <script>
class VirtualList {
constructor(options) {
this.container = options.container;
this.data = options.data || [];
this.itemHeight = options.itemHeight || 50;
this.bufferSize = options.bufferSize || 5; this.phantom = this.container.querySelector('.list-phantom');
this.content = this.container.querySelector('.list-content'); this.startIndex = 0;
this.endIndex = 0;
this.scrollTop = 0; this.init();
} init() {
// 设置占位容器的高度
this.phantom.style.height = this.data.length * this.itemHeight + 'px'; // 监听滚动事件
this.container.addEventListener('scroll', this.handleScroll.bind(this)); // 初始渲染
this.updateVisibleItems();
} handleScroll() {
// 获取当前滚动位置
this.scrollTop = this.container.scrollTop; // 更新可见项
this.updateVisibleItems();
} updateVisibleItems() {
// 计算开始和结束索引
this.startIndex = Math.floor(this.scrollTop / this.itemHeight);
this.endIndex = this.startIndex + Math.ceil(this.container.clientHeight / this.itemHeight); // 添加缓冲区
this.startIndex = Math.max(0, this.startIndex - this.bufferSize);
this.endIndex = Math.min(this.data.length, this.endIndex + this.bufferSize); // 计算偏移量
const offsetY = this.startIndex * this.itemHeight; // 设置内容容器的偏移
this.content.style.transform = `translateY(${offsetY}px)`; // 渲染可见项
this.renderItems();
} renderItems() {
// 清空内容容器
this.content.innerHTML = ''; // 渲染可见项
for (let i = this.startIndex; i < this.endIndex; i++) {
const item = document.createElement('div');
item.className = 'list-item';
item.innerHTML = this.renderItemContent(this.data[i], i);
item.style.height = this.itemHeight + 'px';
this.content.appendChild(item);
}
} renderItemContent(item, index) {
return `<div>索引: ${index}, 内容: ${item}</div>`;
}
} // 生成测试数据
const data = Array.from({ length: 10000 }, (_, i) => `列表项 ${i + 1}`); // 初始化虚拟列表
const virtualList = new VirtualList({
container: document.getElementById('virtualList'),
data: data,
itemHeight: 50,
bufferSize: 10
});
</script>
</body>
</html>
5.最后总结
为什么滚动到指定位置后会将对应区域数据渲染?
1.监听滚动事件
2.滚动触发数据更新方法
3.根据滚动距离计算当前数据索引
4.根据可视区域计算要渲染数据项
5.渲染数据
6.定位内容
原生JS实现虚拟列表(不使用Vue,React等前端框架)的更多相关文章
- 原生js移动端列表无缝间歇向上滚动
在项目开发中尤其是在项目的活动页面的开发中,经常需要将用户的购买信息或中奖信息等以列表的形式展示在页面当中,并可以使其自动间歇向上滚动来达到在有限的区域内展示所有信息的目的.通常的做法是通过将列表父元 ...
- 手把手教你使用Vue/React/Angular三大框架开发Pagination分页组件
DevUI是一支兼具设计视角和工程视角的团队,服务于华为云DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师.官方网站:devui.designNg组件库:ng-devui(欢迎S ...
- 从DOM操作看Vue&React的前端组件化,顺带补齐React的demo
前言 接上文:谈谈我对前端组件化中“组件”的理解,顺带写个Vue与React的demo 上次写完博客后,有朋友反应第一内容有点深,看着迷迷糊糊:第二是感觉没什么使用场景,太过业务化,还不如直接写Vue ...
- angular vue react web前端三大主流框架的对比
首先,我们先了解什么是MVX框架模式? MVX框架模式:MVC+MVP+MVVM 1.MVC:Model(模型)+View(视图)+controller(控制器),主要是基于分层的目的,让彼此的职责分 ...
- 原生js实现音乐列表(隔行换色、全选)
一.实现原理: 1.使用 % 运算符实现各行换色,规律:当%前面的值和后面的值相同时 结果为0: 2.使用开关思想,实现在同一个元素上反复点击时的条件判断,并且把开关以属性方式绑定在每个元素上: 3 ...
- vue项目使用前端框架开发,实现滑动效果,若不刷新页面则无法达到预期效果的问题及解决方法
滑动等效果的初始化时机很重要,在vue项目开发中,需到mounted()钩子函数 (当组件中的DOM结构被渲染好并放到页面中后,会执行这个钩子函数,此时即可初始化滑动效果的js代码). 若组件未挂载到 ...
- 手把手教你使用VUE+SpringMVC+Spring+Mybatis+Maven构建属于你自己的电商系统之vue后台前端框架搭建——猿实战01
猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,跟着教程走下来,变身猿人找到工作不是 ...
- 原生JS实现树状结构列表
树状结构列表,这个技术点之前有写过了,是基于vue讲解,但似乎都没有解决痛点,最基础的原生JS该怎么实现呢? 这篇文章会全面详细的介绍树状结构列表的实现,从数据处理成树状结构,到动态生成dom节点渲染 ...
- 导航栏中各按钮在点击当前按钮变色其他按钮恢复为原有色的实现方法(vue、jq、原生js)
一.vue如何实现? 代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- vue实现实时监听文本框内容的变化(最后一种为原生js)
一.用watch方法监听这个变量. <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...
随机推荐
- Qt音视频开发17-海康sdk解码
一.前言 在视频监控行业领域,海康当之无愧是老大,稳坐第一的宝座很多年了,近期需要将视频监控系统改成采用海康sdk的内核,于是特意去查阅了sdk的使用手册,sdk相关的文档和文件可以直接官网下载到,而 ...
- 9.4classtest rewrite(仓库管理系统)
第一部分,设计界面以及类的定义. import java.util.Scanner; public class viovo { static int number = 5;//五个商品信息 stati ...
- OGC——WFS服务
一.WFS简介 OGC的WMS和WMTS规范都是有关空间数据显示的标准,而WFS(Web Feature Service)则允许用户在分布式的环境下通过HTTP对空间数据进行增.删.改.查. 具 ...
- 论文解读 原苏木素A通过靶向ACSL4/FTH1轴依赖性铁凋亡保护阿霉素诱导的心肌损伤和心功能障碍
同学们,大家好!今天给大家介绍一篇研究性论文,原苏木素A通过靶向ACSL4/FTH1轴依赖性铁凋亡保护阿霉素诱导的心肌损伤和心功能障碍,想了解这方面的同学们可以重点关注一下.这篇文章是2024年7月份 ...
- 当github遇到了Halloween,神奇的彩蛋出现了!
往年每个万圣节github都会修改配色方案,今天才发现,so记录这个不平凡的2020年的github的彩蛋,希望一切都会慢慢好起来.
- Solution Set - Codeforces Global Round 1~8
目录 Codeforces Global Round 1 A. Parity B. Tape C. Meaningless Operations D. Jongmah E. Magic Stones ...
- nginx详细参数配置(史上最全)
Nginx (engine x) 是一个轻量级高性能的HTTP和反向代理服务器,同时也是一个通用 代理服务器 (TCP/UDP/IMAP/POP3/SMTP),最初由俄罗斯人Igor Sysoev编写 ...
- OxyPlot:一个功能强大、漂亮.Net跨平台开源绘图库
推荐一个支持多平台.多框架的.Net绘图库. 01 项目简介 OxyPlot是一个基于.NET开发的.跨平台的绘图库,可用于多种平台和框架,如WPF.Windows 8.Windows Phone.W ...
- 《Linux shell 脚本攻略》第1章——读书笔记
目录 文件描述符及重定向 函数和参数 迭代器 算术比较 文件系统相关测试 字符串进行比较 文件描述符及重定向 echo "This is a sample text 1" > ...
- Access pg walkthrough Intermediate window域渗透
namp nmap -p- -A -sS -T4 192.168.200.187 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-12-23 00 ...