学会前端虚拟滚动,看这篇就够了

一. 虚拟滚动是什么?

前端虚拟滚动是一种用于优化长列表或大量数据展示的技术。它的主要原理是只渲染用户当前可见区域的数据,而不是一次性渲染整个列表或数据集。

在传统的列表渲染中,如果数据量很大,渲染所有数据可能会导致性能下降,特别是在滚动时。虚拟滚动通过动态计算可见区域的位置和需要渲染的数据范围,只渲染可见区域内的部分数据,并在滚动时实时更新渲染的内容。

总结下就是:

  1. 接口返回了大量数据,前端将大量数据保存起来;
  2. 虚拟滚动的策略是:因为无论你返回了多大的数据量,用户可以看到的永远只是可视区域展示的数据,只是大量数据的很少一部分,所以保证可视区域的数据正常渲染就行。

二. 虚拟滚动怎么实现?

先上代码直观体验下

index.vue

<template><div class="container"><my-virtual-scroller :items="list" /></div>
</template><script>
import myVirtualScroller from './myVirtualScroller.vue'
// 模拟一个长列表
const list = []
for(let i=0; i<10000; i++) {list.push({id: i,label: `virtual-list ${i}`})
}
export default {components: {myVirtualScroller},data() {return {list: list}}
}
</script><style scoped>
.container {height: 300px;border: 1px solid #ccc;
}
</style>

myVirtualScroller.vue

// 传入数据可以实现虚拟滚动事件
// 这是一个封装好的子组件 传入数组进行渲染
<template><!-- 最底层的可视区容器 --><div ref="list" class="infinite-list-container" @scroll="scrollEvent($event)"><!-- 中间的可滚动区域,z-index=-1,高度和真实列表相同,目的是出现相同的滚动条 --><divclass="infinite-list-phantom":style="{ height: listHeight + 'px' }"></div><!-- 最上层的可视区列表,数据和偏移距离随着滚动距离的变化而变化 --><div class="infinite-list" :style="{ transform: getTransform }"><divclass="infinite-list-item"v-for="item in visibleData":key="item.id":style="{ height: itemSize + 'px' }">{{ item.label }}</div></div></div>
</template><script>
export default {name: "MyVirtualList",props: {//父组件传过来的数据items: {type: Array,default: () => [],},//可视区域每一项的高度 没有传参的话默认高度是100pxitemSize: {type: Number,//没有高度的话 高度会默认是100pxdefault: 100,},},computed: {//列表总高度listHeight() {// 计算当前传值数据的总长度 * 每个盒子的高度 计算出所有数据的整体高度return this.items.length * this.itemSize;},//可视区列表的项数visibleCount() {return Math.ceil(this.screenHeight / this.itemSize);},//可视区列表偏移距离对应的样式getTransform() {return `translate3d(0,${this.startOffset}px,0)`;},//获取可视区列表数据visibleData() {// 截取出可视区域显示的盒子 进行渲染return this.items.slice(this.start,Math.min(this.end, this.items.length));},},mounted() {// 获取可是区域的高度this.screenHeight = this.$refs.list.clientHeight;// 开始this.start = 0;// 结束this.end = this.start + this.visibleCount;},data() {return {screenHeight: 0, //可视区域高度startOffset: 0, //偏移距离start: 0, //起始索引end: 0, //结束索引};},methods: {scrollEvent() {//当前滚动条滚动位置let scrollTop = this.$refs.list.scrollTop;//此时的开始索引 使用当前滚动条高度 / 盒子高度 拿到的是当前是哪一个盒子为第一个this.start = Math.floor(scrollTop / this.itemSize);//此时的结束索引//获取到当前第一个盒子的数值 加 计算好可视区域可容纳多少盒子的值this.end = this.start + this.visibleCount;//此时的偏移距离this.startOffset = scrollTop - (scrollTop % this.itemSize);},},
};
</script><style scoped>
.infinite-list-container {height: 100%;overflow: auto;position: relative;
}.infinite-list-phantom {position: absolute;left: 0;top: 0;right: 0;
}.infinite-list {left: 0;right: 0;top: 0;position: absolute;
}.infinite-list-item {line-height: 50px;text-align: center;color: #555;border: 1px solid #ccc;box-sizing: border-box;
}
</style>

虚拟滚动的思路总结如下

1. 确定视窗位置:通过获取列表滚动区域的scrollTop属性,确定当前视窗的位置;

2. 计算需要渲染的节点:根据视窗位置和子节点的高度,计算出需要真实渲染的节点范围。可以使用Math.floor(scrollTop/itemHeight)和Math.ceil(viewHeight/itemHeight)来确定起始索引和渲染的节点数量;

3. 移动渲染的节点到视窗内:将需要渲染的节点移动到视窗内,可以通过修改节点的位置或使用其他方式实现;

4. 按需加载数据:根据滚动位置,动态加载相应的数据,只加载当前视窗可见范围内的数据,减少数据量和渲染负担;

5. 处理滚动事件:监听滚动事件,根据滚动位置实时更新需要渲染的节点和数据。

三. 虚拟滚动示例代码难点解析

1. 可视化容器为什么要包裹两个盒子,并且设置绝对定位?

第一个盒子(类名为"infinite-list-phantom")的作用:
其总高度为内容的总高度,主要要为了撑起父盒子,使父盒子有滚动条。
第二个盒子(类名为‘infinite-list’)的作用:
这个要可视区域,是用户所能看到的界面,也是数据渲染的界面。

至于为什么要设置绝对定位,是因为需要第二个盒子覆盖第一个盒子,以满足第二个盒子展现在可视界面。

2. 为什么要设置:style=“{ transform: getTransform }”?

原因如下:

  1. 因为可视界面区域有限,在滚动后,会展示总的内容区域和可视区域不相交的部分,在可视区域就会出现部分或全部空白。
  2. 滚动的过程本质要内容区域的位置变化,其变化的数值可以通过scrollTop来查看;
  3. 通过transform的作用,抵消scrollTop的位置变动,使得我们看到的还是原先的可视区域位置的dom节点,只不过在滚动的过程中,渲染数据会改变。

3.为什么要设置偏移距离?

相关代码如下:

 //此时的偏移距离this.startOffset = scrollTop - (scrollTop % this.itemSize);

原因如下:

  1. 为了使得滚动的时候有动态效果,体验会更好;
  2. 可以尝试将scrollTop - 改成 scrollTop + 测试,就可以更好的去理解2、3点疑问。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/18775.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

四川易点慧电商抖音小店信誉之店

在当下这个电商飞速发展的时代&#xff0c;如何在众多网店中挑选出一家既可靠又值得信赖的店铺&#xff0c;成为了消费者们关注的焦点。四川易点慧电子商务有限公司抖音小店以其卓越的品质和诚信的经营&#xff0c;逐渐在抖音平台上崭露头角&#xff0c;成为了众多消费者心中的…

HDRnet

local feature and global feature 在这里插入图片描述 Local features and Global features in Image Local feature also known as local descriptors, are distinct, informative characteristics of an image or video frame that are used in computer vision and image…

electron应用安装包瘦身

在win-unpacked目录下 在resources目录下借助asar查看编译后文件 pnpm add asar -g # asar extract /[sourcePath]/app.asar /[targetPath]/app文件夹中的产物有render和main编译文件 其中有soruceMap文件可以通过配置删除 node-modules目录下确认如果没有跨平台需要都移动到…

随机生成pytorch算子测试序列且保证算子参数合法

随机生成pytorch算子测试序列且保证算子参数合法 代码输出 背景: 1.一些对维度进行操作的算子的单算子测试,结果正常,但多个算子组合在一起,结果就不对。是否能给一个算子列表,随机生成它们的组合呢 功能描述: 1.此程序用于在 CUDA 环境中生成随机张量并对其施加一系列随机选…

PHP 汉字转拼音

使用 overtrue/pinyin 库将汉字转换为拼音 在这篇文章中&#xff0c;我将向大家介绍如何使用 overtrue/pinyin 库来将汉字转换为拼音。这是一个非常方便的PHP库&#xff0c;能够帮助我们轻松地进行汉字到拼音的转换。 安装 overtrue/pinyin 库 首先&#xff0c;我们需要通过 C…

redis--集群节点维护

添加节点 因公司业务发展迅猛&#xff0c;现有的三主三从redis cluster架构可能无法满足现有业务的并发写入需求&#xff0c;因此公司紧急采购一台服务器192.168.7.107&#xff0c;需要将其动态添加到集群当中其不能影响业务使用和数据丢失&#xff0c;则添加过程如下: 同步之…

Pandas-中axis的用法

在Pandas中&#xff0c;min(axis)方法是计算DataFrame或Series中每行或每列的最小值的函数。该函数可以接受一个参数axis&#xff0c;用于指定计算最小值的方向。当axis0时&#xff0c;表示沿着行的方向计算最小值&#xff1b;当axis1时&#xff0c;表示沿着列的方向计算最小值…

买入看跌期权怎么理解?

今天带你了解买入看跌期权怎么理解&#xff1f;看跌期权买入者往往预期市场价格将下跌。 买入看跌期权怎么理解&#xff1f; 买入看跌期权是指购买者支付权利金&#xff0c;获得以特定价格向期权出售者卖出一定数量的某种特定商品的权利。看跌期权买入者往往预期市场价格将下跌…

【YOLOv5/v7改进系列】引入AKConv——即插即用的卷积块

一、导言 介绍了一种名为AKConv&#xff08;Alterable Kernel Convolution&#xff09;的新型卷积操作&#xff0c;旨在解决标准卷积操作存在的两个根本性问题。首先&#xff0c;标准卷积操作受限于局部窗口&#xff0c;无法捕获来自其他位置的信息&#xff0c;且其采样形状固…

软件系统测试的类型和方法介绍

测试是软件开发过程中至关重要的一环&#xff0c;负责验证和确认软件系统是否符合预期的需求&#xff0c;并帮助开发团队消除潜在的缺陷。系统测试作为软件测试中不可缺少的过程&#xff0c;是根据预先制定的测试计划和测试用例&#xff0c;以检查软件系统功能、性能、安全性和…

JavaScript tab选项卡切换

下面是一个简单的JavaScript代码示例&#xff0c;展示如何使用tab选项卡来切换内容。 HTML代码&#xff1a; <div class"tab"><button class"tablinks" onclick"openTab(event, tab1)">选项卡1</button><button class&qu…

仿真51单片机程序(下载安装+Proteus)

我是看的这个大佬的:http://t.csdnimg.cn/Z07SZ 大佬写的很详细了,我就不献丑了. 贴上俩个运行成功的截图,有碰到问题的欢迎交流.

初识BootLoader

一、 BootLoader的概念 引导加载程序是系统加电后运行的第一段软件代码。回忆一下PC的体系结构我们可以知道&#xff0c;PC机中的引导加载程序由BIOS&#xff08;本质是一段固件程序&#xff09;和位于硬盘MBR中的BootLoader&#xff08;如LILO、GRUB等&#xff09;组成。BIOS…

【学习Day2】计算机基础

✍&#x1f3fb;记录学习过程中的输出&#xff0c;坚持每天学习一点点~ ❤️希望能给大家提供帮助~欢迎点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;指点&#x1f64f; 1.4 校验码 奇偶校验 ● 奇偶校验码的编码方法是&#xff1a; 由若干位有效信息的头部或者…

探寻数据处理的高效之道:从Python内置方法到NumPy的飞跃

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;为什么要学习NumPy&#xff1f; 二、案例展示&#xff1a;创建整数序列…

idm软件是做什么的 IDM是啥软件 idm软件怎么下载 idm软件怎么下载

一、IDM是啥软件 IDM 是由美国 Tonec 公司开发的 Windows 软件&#xff0c;该软件最初于 2005 年发布。IDM全称Internet Download Manager&#xff0c;是一款Windows平台老牌而功能强大的下载加速器&#xff0c;专注于互联网数据下载。这款软件是一款不错的轻量级下载工具&…

关于如何在 smartforms 中 debug

发现一旦smartforms 复杂起来&#xff0c;Debug的时候就一下子找不到指定位置&#xff0c;所以如何才能最简单的找到指定位置呢 以这个为案例 然后打上断点即可debug

Java实现AES,DES,RSA加密

Java的Cipher类 Cipher类提供了加密和解密的功能。 Cipher类可以完成aes&#xff0c;des&#xff0c;des3和rsa等加密方式 AES加密算法 介绍 这个标准用来替代原先的DES,AES加密过程涉及到4种操作&#xff0c;分别是字节替代、行移位、列混淆和轮密钥加。解密过程分别为对…

相对论表明速度越快时间越慢,为什么速度会影响时间?

在物理学的宏伟殿堂中&#xff0c;相对论以其深邃的洞察力&#xff0c;挑战了我们对时间和空间的传统认识。1905年&#xff0c;阿尔伯特爱因斯坦提出了狭义相对论&#xff0c;揭示了在所有惯性参照系中&#xff0c;光速是常数的惊人事实。 随后在1915年&#xff0c;他进一步发展…

YOLOv5数据集的文件结构和文件格式以及标注工具LabelImg的说明文档

文章目录 一 概述二 文件结构与数据格式2.1 数据集的文件结构2.2 数据格式2.2 文件结构2.3 标注文件的注意事项 三 手动标注YOLOv5数据集3.1 标注工具的选择3.2 标注流程 四 总结与注意事项4.1 labelImg的使用技巧与说明4.2 注意事项 一 概述 YOLOv5 是一个采用深度学习技…