网站首页 > 文章精选 正文
引言
在现代Web应用中,处理大量数据的展示是一个常见的挑战。无论是社交媒体的时间线、电商平台的商品列表,还是新闻网站的文章流,如何高效地加载和渲染大量内容,同时保持良好的用户体验,是开发者需要解决的关键问题。传统的做法是将所有数据一次性加载到页面上,但这会导致页面加载缓慢、内存占用过高,甚至影响浏览器的响应速度。为了解决这些问题,滚动加载更多(Infinite Scroll) 和 虚拟列表(Virtual List) 成为了流行的解决方案。
两种方案的介绍以及区别
- 滚动加载更多(Infinite Scroll) :
- 工作原理:滚动加载更多通过分页的方式工作。当用户滚动到页面底部或接近底部时,系统会触发一个新的请求,获取下一页的数据,并将其动态添加到现有内容的末尾。这种方式允许用户在不中断浏览的情况下,无缝加载更多内容。
- 优点:实现简单,用户体验流畅,减少了初始加载时间。
- 缺点:随着用户不断滚动,页面上的DOM元素会逐渐增加,可能导致内存占用过高,影响性能。对于非常大的数据集,滚动加载更多可能会导致页面变得非常沉重,影响用户体验。
- 虚拟列表(Virtual List) :
- 工作原理:虚拟列表的核心思想是只渲染当前视口(即用户可以看到的部分)中的内容,而不是一次性将所有数据加载到DOM中。当用户滚动时,虚拟列表会动态地更新DOM,确保只有可见区域的内容被渲染。此外,虚拟列表通常会复用DOM节点,进一步减少DOM操作的开销。
- 优点:即使数据量非常大,虚拟列表也能保持良好的性能,因为它只渲染可见区域的内容。它还非常适合处理海量数据,避免了内存占用过高的问题。
- 缺点:实现相对复杂,尤其是需要处理滚动事件、DOM复用、边界条件等。通常建议使用现成的库(如 vue-virtual-scroller、react-window 等)来简化开发过程。
滚动加载更多的实现
使用@scroll
1. 实现
通过监听滚动条的变化来更新页码,实现加载更多效果;代码里面有注释,我就不多说啦。需要注意的是父盒子的高度很重要。
以下是代码(但是先别拿去用,因为还有重要的优化)
<template>
<div class="color-squares" @scroll="handleScroll">
<!-- 这里我使用的是一个数字并非是一个数组,如果使用的是数组的话可将size换成arr.slice(0,size)(arr是你的数组); -->
<div v-for="(item, index) in size" :key="index" class="square">
{{ item }}
</div>
<!-- 末尾方式加载状态,这里我使用的时t-design(腾讯组件库) -->
<t-loading :loading="loading" text="正在加载更多..." />
</div>
</template>
<script setup>
import { ref, onMounted, computed } from "vue";
//总数据量
const total = ref(15);
//我们手动模拟分页效果,
const pageSize = ref(5);
const pageNum = ref(1);
const loading = ref(false);
//使用计算属性来更改size的值。通过滚动来更改pageNum(页码)。
const size = computed(() => {
return pageNum.value * pageSize.value > total
? total
: pageNum.value * pageSize.value;
});
//加载更多函数,注意里面的打印信息。
const loadMore = () => {
if (pageNum.value * pageSize.value >= total.value) {
loading.value = false;
return;
}
loading.value = true;
//请注意我
console.log(1);
// 模拟异步请求
setTimeout(() => {
pageNum.value++;
loading.value = false;
}, 1000); // 模拟网络延迟
};
const handleScroll = (event) => {
const container = event.target;
if (
container.scrollTop + container.clientHeight >=
container.scrollHeight - 5
) {
loadMore();
}
};
// 生命周期钩子
onMounted(() => {});
</script>
<style scoped>
.color-squares {
height: 100vh;
overflow-y: scroll;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
line-height: 100px;
width: 100%;
gap: 10px;
border: 1px solid #ccc;
}
.square {
width: 200px;
height: 200px;
background-color: #ececec;
text-align: center;
line-height: 200px;
border-radius: 8px;
font-size: 24px;
font-weight: bolder;
}
</style>
2. 上述的缺陷以及优化
直接看效果图,我们可以看到我们轻轻滚动一下,loadMore就触发了多次。注意控制台打印信息打印的13个1,意味着一次滚动触发了loadMore 13次
所以我们理所当然需要给他加上防抖
<script setup>
import { ref, onMounted, computed } from "vue";
//总数据量
const total = ref(15);
//我们手动模拟分页效果,
const pageSize = ref(5);
const pageNum = ref(1);
const loading = ref(false);
//使用计算属性来更改size的值。通过滚动来更改pageNum(页码)。
const size = computed(() => {
return pageNum.value * pageSize.value > total
? total
: pageNum.value * pageSize.value;
});
//加载更多函数,注意里面的打印信息。
const loadMore = () => {
if (pageNum.value * pageSize.value >= total.value) {
loading.value = false;
return;
}
loading.value = true;
//请注意我
console.log(1);
// 模拟异步请求
setTimeout(() => {
pageNum.value++;
loading.value = false;
}, 1000); // 模拟网络延迟
};
function debounce(fn, delay, immediate = false) {
let timer;
return function (...args) {
const context = this;
// 如果设置了 immediate,并且这是第一次触发,则立即执行目标函数
if (immediate && !timer) {
fn.apply(context, args);
}
// 清除之前的定时器
if (timer) clearTimeout(timer);
// 设置新的定时器
timer = setTimeout(() => {
if (!immediate) {
fn.apply(context, args); // 如果没有立即执行,则在延迟后执行
}
timer = null; // 清空定时器标识符
}, delay);
};
}
const handleScroll = debounce((event) => {
const container = event.target;
if (
container.scrollTop + container.clientHeight >=
container.scrollHeight - 5
) {
loadMore();
}
}, 300);
// 生命周期钩子
onMounted(() => {});
</script>
加了防抖的效果
使用 Element Plus 的无限滚动指令 (v-infinite-scroll)(最快)
在需要添加无限滚动的盒子中加上 v-infinite-scroll指令该指令需要绑定一个函数。无需设置防抖,无需监听滚动,拿来即用。
具体代码如下:
<template>
<div class="color-squares" max-height="500px" v-infinite-scroll="loadMore">
<!-- 如果使用的是数组,可以将 size 换成 arr.slice(0, size) -->
<div v-for="(item, index) in size" :key="index" class="square">
{{ item }}
</div>
<!-- 末尾方式加载状态,这里我使用的时 t-design(腾讯组件库) -->
<t-loading :loading="loading" text="正在加载更多..." />
</div>
</template>
<script setup>
import { ref, onMounted, computed } from "vue";
//总数据量
const total = ref(15);
//我们手动模拟分页效果,
const pageSize = ref(5);
const pageNum = ref(1);
const loading = ref(false);
//使用计算属性来更改size的值。通过滚动来更改pageNum(页码)。
const size = computed(() => {
return pageNum.value * pageSize.value > total
? total
: pageNum.value * pageSize.value;
});
//加载更多函数,注意里面的打印信息。
const loadMore = () => {
if (pageNum.value * pageSize.value >= total.value) {
loading.value = false;
return;
}
loading.value = true;
//请注意我
console.log(1);
// 模拟异步请求
setTimeout(() => {
pageNum.value++;
loading.value = false;
}, 1000); // 模拟网络延迟
};
</script>
<style scoped>
.color-squares {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
line-height: 100px;
width: 100%;
gap: 10px;
border: 1px solid #ccc; /* 可选:添加边框以便更清晰地看到滚动容器 */
}
.square {
width: 200px;
height: 200px;
background-color: #ececec;
text-align: center;
line-height: 200px;
border-radius: 8px;
font-size: 24px;
font-weight: bolder;
}
</style>
看看效果图:
结语
通过本期文章,我们掌握了两种常见的滚动加载更多实现方式:手动处理滚动事件 和 使用 Element Plus 的无限滚动指令。这两种方法各有优劣,适用于不同的场景。在下一期文章中,我们将进一步探讨如何使用 Intersection Observer API 来检测元素的重叠度,从而实现更加灵活和高效的滚动加载更多功能。
- 上一篇: 前端CSS 布局必备知识-BFC
- 下一篇: 前端进阶高薪必看-CSS篇
猜你喜欢
- 2025-01-04 「炫丽」从0开始做一个WPF+Blazor对话小程序
- 2025-01-04 adonisjs的模板以及路由
- 2025-01-04 5、谈谈你对BFC的理解?
- 2025-01-04 前端 BFC、IFC、GFC 和 FFC,这些你都知道吗?
- 2025-01-04 Wijmo5 Flexgrid基础教程:自定义编辑器
- 2025-01-04 H5小游戏开发教程之页面基础布局的开发
- 2025-01-04 web前端:CSS的常用属性速查表
- 2025-01-04 用网页做个ppt- 定时全屏切换图片
- 2025-01-04 HTML翻牌器:用CSS和HTML元素创造动态数字展示
- 2025-01-04 「网络安全」安全设备篇(漏洞扫描器-流量监控-安全审计产品)
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 稳压管的稳压区是工作在什么区 (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)