Vue实现滚动加载更多效果的示例代码

 更新时间:2024年12月15日 08:42:06   作者:小前端小小小白  
这篇文章介绍了在 Web 应用中处理大量数据展示的两种滚动加载更多方案,滚动加载更多通过分页工作,优点是实现简单、用户体验流畅,缺点是内存占用可能过高,虚拟列表只渲染视口内容,性能好但实现复杂,本文介绍了Vue实现滚动加载更多效果,需要的朋友可以参考下

引言

在现代Web应用中,处理大量数据的展示是一个常见的挑战。无论是社交媒体的时间线、电商平台的商品列表,还是新闻网站的文章流,如何高效地加载和渲染大量内容,同时保持良好的用户体验,是开发者需要解决的关键问题。传统的做法是将所有数据一次性加载到页面上,但这会导致页面加载缓慢、内存占用过高,甚至影响浏览器的响应速度。为了解决这些问题,滚动加载更多(Infinite Scroll)虚拟列表(Virtual List) 成为了流行的解决方案。

两种方案的介绍以及区别

  • 滚动加载更多(Infinite Scroll)

    • 工作原理:滚动加载更多通过分页的方式工作。当用户滚动到页面底部或接近底部时,系统会触发一个新的请求,获取下一页的数据,并将其动态添加到现有内容的末尾。这种方式允许用户在不中断浏览的情况下,无缝加载更多内容。
    • 优点:实现简单,用户体验流畅,减少了初始加载时间。
    • 缺点:随着用户不断滚动,页面上的DOM元素会逐渐增加,可能导致内存占用过高,影响性能。对于非常大的数据集,滚动加载更多可能会导致页面变得非常沉重,影响用户体验。
  • 虚拟列表(Virtual List)

    • 工作原理:虚拟列表的核心思想是只渲染当前视口(即用户可以看到的部分)中的内容,而不是一次性将所有数据加载到DOM中。当用户滚动时,虚拟列表会动态地更新DOM,确保只有可见区域的内容被渲染。此外,虚拟列表通常会复用DOM节点,进一步减少DOM操作的开销
    • 优点:即使数据量非常大,虚拟列表也能保持良好的性能,因为它只渲染可见区域的内容。它还非常适合处理海量数据,避免了内存占用过高的问题。
    • 缺点:实现相对复杂,尤其是需要处理滚动事件、DOM复用、边界条件等。通常建议使用现成的库(如 vue-virtual-scrollerreact-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 来检测元素的重叠度,从而实现更加灵活和高效的滚动加载更多功能。

以上就是Vue实现滚动加载更多效果的示例代码的详细内容,更多关于Vue滚动加载更多效果的资料请关注脚本之家其它相关文章!

相关文章

  • vue对于低版本浏览器兼容问题的解决思路

    vue对于低版本浏览器兼容问题的解决思路

    很多时候使用vue开发的项目,由于无法在低版本浏览器上运行,所以需要解决下,下面这篇文章主要给大家介绍了关于vue对于低版本浏览器兼容问题的解决思路,需要的朋友可以参考下
    2023-02-02
  • Vue使用高德地图搭建实时公交应用功能(地图 + 附近站点+线路详情 + 输入提示+换乘详情)

    Vue使用高德地图搭建实时公交应用功能(地图 + 附近站点+线路详情 + 输入提示+换乘详情)

    这篇文章主要介绍了vue中使用高德地图搭建实时公交应用(地图 + 附近站点+线路详情 + 输入提示+换乘详情),主要是让大家熟悉下高德地图在vue中的使用及vue的常用指令,需要的朋友可以参考下
    2018-05-05
  • 详解Vuex下Store的模块化拆分实践

    详解Vuex下Store的模块化拆分实践

    这篇文章主要介绍了详解Vuex下Store的模块化拆分实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-07-07
  • vue3封装简易的vue-echarts问题

    vue3封装简易的vue-echarts问题

    这篇文章主要介绍了vue3封装简易的vue-echarts问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • 使用vscode添加vue模板步骤示例

    使用vscode添加vue模板步骤示例

    这篇文章主要为大家介绍了vscode添加vue模板步骤示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • Vue CLI 命令行打包配置自定义参数方式

    Vue CLI 命令行打包配置自定义参数方式

    这篇文章主要介绍了Vue CLI 命令行打包配置自定义参数方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • vue如何在线预览各类型文件

    vue如何在线预览各类型文件

    这篇文章主要介绍了vue如何在线预览各类型文件问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • vue ssr+koa2构建服务端渲染的示例代码

    vue ssr+koa2构建服务端渲染的示例代码

    这篇文章主要介绍了vue ssr+koa2构建服务端渲染的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • 使用Vue-scroller页面input框不能触发滑动的问题及解决方法

    使用Vue-scroller页面input框不能触发滑动的问题及解决方法

    这篇文章主要介绍了使用Vue-scroller页面input框不能触发滑动的问题,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • vue如何自定义配置运行run命令

    vue如何自定义配置运行run命令

    这篇文章主要介绍了vue如何自定义配置运行run命令,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04

最新评论