赞
踩
于常见的触底懒加载的优劣对比
优势:
- 滚动平滑性: 虚拟列表可以在滚动时实时渲染可见区域内的数据,保持滚动的平滑性,不会因为数据量大而导致滚动卡顿。
- 性能优化: 虚拟列表能够有效减少渲染的 DOM 元素数量,从而提高页面的性能和响应速度。
- 快速渲染: 虚拟列表根据滚动位置计算需要渲染的数据,渲染速度较快,可以更快地展示数据。
劣势:
- 不适用动态数据: 虚拟列表适用于静态数据或数据变化不频繁的情况,对于动态变化的数据需要额外的处理。
效果展示
创建一个父级div
主要添加下面两个属性,其他样式随便
overflow: auto;
position: relative;
然后添加子级div仅用于撑开父级,高度是根据数据量来的,我这里模拟1w条数据 高度55w px
然后再添加 存放数据的盒子 使用绝对定位
数据展示
实现逻辑
滚动实际是撑开的div实现的,与数据展示没有关系,展示数据的box盒子 使用绝对定位和top 让它一直固定在能看到的位置
数据的展示:
上图中可以看到,第一跳数据已经滚动到了顶部以外,当它超出一个行高的时候 它就会被删除替换成地二条数据 比如 开始是 0--9 当滑动的时候 他就变成了 1 -- 10 然后top下移一个行高。
在下边我们看到除了能看到的22 在dom里面还有24 这个就是防止下滑太快导致出现空白区域的
完整代码
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <style>
- .content{
- width: 500px;
- height: 550px;
- border: #2d9f75 1px solid;
- overflow: auto;
- margin: 0 auto;
- position: relative;
- }
- .item-box{
- position: absolute;
- width: 100%;
- top: 0; /* Add top: 0; */
- left: 0; /* Add left: 0; */
- }
- .item-li{
- width: 100%;
- text-align: center;
- height: 55px;
- line-height: 55px;
- border: antiquewhite 0.5px solid;
- }
- </style>
- </head>
- <body>
-
- <div id="app">
- <div class="content" ref="contentRef" @scroll="handleScroll">
- <!-- 根据总条数和 每行的高度 计算出 高度,次div 只用于撑开父级 出现滚动条-->
- <div :style="{'height':`${total * this.lineHeight}px`}"></div>
- <!-- 用于绝对定位,展示可视窗口数据-->
- <div class="item-box">
- <div v-for="(item,index) in visibleList" :key="index" class="item-li">{{item.name}}</div>
-
- </div>
-
- </div>
- </div>
- <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
- <script>
- var app = new Vue({
- el: '#app',
- data: {
- total:10000,// 总条数 ,也可根据list数组长度计算
- lineHeight:55,// 每一行高度
- bufferSize:2,// 缓冲数
- list:[],// 原数组
- visibleList: [],// for循环 展示的数组
- },
- methods:{
- updateVisibleList() {
- // 获取父级div dom计算距离顶部距离
- const content = this.$refs.contentRef;
- // 获取浮动div 设置top值
- const itemBox = this.$el.querySelector('.item-box');
- // content.scrollTop 是当前滚动条距离顶部的距离 / this.lineHeight(每行高度) 得出可视窗口内 展示的数据开始下标
- const startIndex = Math.floor(content.scrollTop / this.lineHeight);
- /* content.clientHeight 可视窗口区域高度用于计算 窗口内展示多少行数据 ,
- bufferSize缓冲数 在原数据上多显示两行 防止快速滑动的时候出现白色区域*/
- const endIndex = startIndex + Math.ceil(content.clientHeight / this.lineHeight) + this.bufferSize;
- // list 是1万条数据,visibleList才是正常for循环的数据,需要根据下标赋值
- this.visibleList = this.list.slice(startIndex, endIndex);
- // 设置绝对定位top 使得 itemBox 始终在我们的视线内
- itemBox.style.top = `${startIndex * this.lineHeight}px`;
- },
- handleScroll(){
- this.updateVisibleList();
- }
- },
- mounted(){
- // 构造1万条数据 一般来说是从后端请求的数据
- for (let i = 0; i < this.total;i++) {
- this.list.push({
- name:'name'+i
- })
- }
- this.updateVisibleList();
- }
- })
- </script>
- </body>
- </html>

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。