Vue3中实现数据触底加载

<template>
  <a-spin style="width: 100%" :spinning="spinning" tip="加载中">
    <div class="contain-wrapper" ref="containerRef">
      <ul v-for="v in lists" :key="v.name">
        <li>{{ v.name }}</li>
      </ul>
      <p v-if="showNoMore" class="no-more-data">没有更多数据</p>
      <div v-if="loading" class="loader">Loading...</div>
    </div>
  </a-spin>
</template>

<script setup>
import { reactive, ref, onMounted, onUnmounted, computed } from "vue";

const containerRef = ref(null);
const loading = ref(false);
let scrollHandler = null;
const page = ref(1);
const pageSize = ref(20);
const spinning = ref(false);
const lists = ref([]);
const showNoMore = ref(false);

const list = reactive({
  list: [
    { name: "张三", age: 18 },
    { name: "李四", age: 19 },
    { name: "王五", age: 20 },
    { name: "赵六", age: 21 },
    { name: "孙七", age: 22 },
    { name: "周八", age: 23 },
    { name: "吴九", age: 24 },
    { name: "郑十", age: 25 },
    { name: "王十一", age: 26 },
    { name: "张三", age: 18 },
    { name: "李四", age: 19 },
    { name: "王五", age: 20 },
    { name: "赵六", age: 21 },
    { name: "孙七", age: 22 },
    { name: "周八", age: 23 },
    { name: "吴九", age: 24 },
    { name: "郑十", age: 25 },
    { name: "王十一", age: 26 },
    { name: "张三", age: 18 },
    { name: "李四", age: 19 },
    { name: "王五", age: 20 },
    { name: "赵六", age: 21 },
    { name: "孙七", age: 22 },
    { name: "周八", age: 23 },
    { name: "吴九", age: 24 },
    { name: "郑十", age: 25 },
    { name: "王十一", age: 26 },
    { name: "张三", age: 18 },
    { name: "李四", age: 19 },
    { name: "王五", age: 20 },
    { name: "赵六", age: 21 },
    { name: "孙七", age: 22 },
    { name: "周八", age: 23 },
    { name: "吴九", age: 24 },
    { name: "郑十", age: 25 },
    { name: "王十一", age: 26 },
    { name: "张三", age: 18 },
    { name: "李四", age: 19 },
    { name: "王五", age: 20 },
    { name: "赵六", age: 21 },
    { name: "孙七", age: 22 },
    { name: "周八", age: 23 },
    { name: "吴九", age: 24 },
    { name: "郑十", age: 25 },
    { name: "王十一", age: 26 },
  ],
});

const handleScroll = () => {
  const container = containerRef.value;
  console.log(
    "scrollTop",
    container.scrollTop + container.clientHeight,
    container.clientHeight
  );
  if (
    container.scrollTop + container.clientHeight >= container.scrollHeight &&
    !loading.value
  ) {
    
    loading.value = true;

    setTimeout(async () => {
      const scrollTop = container.scrollTop;
      const MAX_PAGE_SIZE = list.list.length;
      if (pageSize.value + 5 <= MAX_PAGE_SIZE) {
        pageSize.value += 5;
      } else {
        pageSize.value = MAX_PAGE_SIZE;
      }
      await getList(scrollTop).finally(() => {
        loading.value = false;
      });
    }, 1000);
  }
};

const getList = async (scrollTop = 0) => {
  setTimeout(() => { //模拟异步数据
    lists.value = list.list.slice(0, pageSize.value);
    if (pageSize.value >= list.list.length) {
      showNoMore.value = true;
      loading.value = false; // 确保加载状态正确重置
    }
  }, 0);

  if (containerRef.value) {
    containerRef.value.scrollTo(0, scrollTop);
  }
};

onMounted(() => {
  scrollHandler = handleScroll;
  containerRef.value.addEventListener("scroll", scrollHandler, true);
  getList();
});

onUnmounted(() => {
  if (containerRef.value && scrollHandler) {
    containerRef.value.removeEventListener("scroll", scrollHandler, true);
    scrollHandler = null;
  }
});
</script>

<style lang="less" scoped>
.contain-wrapper {
  width: 200px;
  height: 600px;
  border: 1px solid #000;
  margin: 0 auto;
  overflow-x: hidden;
  overflow-y: auto;
}
</style>

Vue3 中,`el-scrollbar` 是 Element UI 提供的一个用于处理滚动条的组件,而触底加载(infinite scroll 或 load more)通常是在列表滚动到底部时动态加载更多数据的技术。要在 Vue 项目中实现这种功能,你可以按照以下步骤操作: 1. 安装依赖:首先确保已安装了 Element UI 和相关的库,例如 `vue-infinite-loading`,可以使用 npm 或者 yarn 进行安装: ```bash npm install element-ui vue-infinite-loading # 或者 yarn add element-ui vue-infinite-loading ``` 2. 引入组件:在你的 Vue 组件中导入 `ElScrollbar` 和无限加载组件,如 `InfiniteScroll`: ```javascript import { ElScrollbar } from &#39;element-plus&#39; import InfiniteScroll from &#39;vue-infinite-loading&#39; ``` 3. 使用模板:将 `ElScrollbar` 和 `InfiniteScroll` 结合起来,并设置滚动事件监听器,当滚动到底部时触发加载更多数据的请求: ```html <template> <div class="scroll-container"> <ElScrollbar :view="list" @scroll="onScroll"> <ul v-if="!isLoading && list.length > 0"> <!-- 渲染你的列表项 --> <li v-for="(item, index) in list" :key="index">{{ item }}</li> </ul> <InfiniteLoading :disabled="isLoading" loading-text="正在加载..." @load="loadMoreData" ></InfiniteScroll> </ElScrollbar> </div> </template> ``` 4. 配置数据和方法:设置列表数据 `list`、加载状态 `isLoading` 和加载更多数据的方法 `loadMoreData`: ```javascript <script> export default { data() { return { list: [], // 初始化为空数组 isLoading: false, // 初始加载状态为 false // ... 其他数据和配置 } }, methods: { onScroll() { if (this.$refs.scrollbar.scrollTop + this.$refs.scrollbar.clientHeight === this.$refs.scrollbar.scrollHeight) { this.isLoading = true; // 设置加载标志为 true } }, loadMoreData() { // 模拟异步加载更多数据 setTimeout(() => { const newData = /* 加载更多的数据源 */; this.list.push(...newData); this.isLoading = false; // 加载完成后,标志设回 false }, 2000); // 调整这里的延迟时间以适应实际网络情况 } } }; </script> ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值