无限滚动分页加载

JavaScriptVue

2023年02月03日 13:44:031593

因为业务需要,特别是列表类页面,为了前后端性能优化,前端往往需要支持分页功能。

目前实现分页主要的两种宏观方案:

  1. 固定分页组件:即分页组件固定展示在某个位置,通过点击页面需要进行分页数据展示。这种方式比较适合PC端等大屏设备,在移动端的体验不是特别好(例:ElementUI的pagination组件)

  2. 无限滚动分页:假设列表高度超过当前容器的高度,当列表底部滚动到距离浏览器窗口底部一定的距离之内时,触发下一页数据的加载。这种方案比较适合移动端,但当数据量过大的时候,需要考虑性能问题。

因为监听浏览器滚动事件非常消耗新能,并且需要格外注意防抖的问题,所以我采取了另外一种方案去实现无限滚动:

IntersectionObserver

当一个 IntersectionObserver 对象被创建时,其被配置为监听根中一段给定比例的可见区域。一旦 IntersectionObserver 被创建,则无法更改其配置,所以一个给定的观察者对象只能用来监听可见区域的特定变化值;然而,你可以在同一个观察者对象中配置监听多个目标元素。

intersectionObserver的浏览器支持情况:

//cdn.shiniest.cn/static/202302/intersectionObserver.png

直接上代码

<template>
  <div class="load-more" ref="loadMoreRef">
    <div v-show="loading" class="icon">
      <i class="x-icon-jiazaizhong"></i>
      <slot name="loading">{{loadingText}}</slot>
    </div>
    <div class="load" v-show="!over && !noData && !loading" @click="emit('load')">
      <slot name="loadText">{{loadText}}</slot>
    </div>
    <div v-show="!noData && over">
      <slot name="loadOverText">{{loadOverText}}</slot>
      
    </div>
    <div v-show="noData">
      <slot name="noDataText">{{noDataText}}</slot>
    </div>
  </div>
</template>
<script setup lang="ts">
const props = defineProps({
  loading: Boolean,
  over: Boolean,
  noData: Boolean,
  loadingText: {
    type: String,
    default: '加载中...'
  },
  loadText: {
    type: String,
    default: '加载更多'
  },
  loadOverText: {
    type: String,
    default: '没有更多啦~'
  },
  noDataText: {
    type: String,
    default: '怎么一条数据都没有呢?'
  }
})
const loadMoreRef = shallowRef();
const emit = defineEmits(['load']);
let intersectionObserver: IntersectionObserver;
let loadTimes = 0;
const maxTimes = 2;
onMounted(() => {
  intersectionObserver = new IntersectionObserver(([{ intersectionRatio }]) => {
    if (!!intersectionRatio && !props.loading && !props.over && !props.noData) {
      if(loadTimes >= maxTimes) {
        intersectionObserver.disconnect();
      } else {
        emit('load');
        loadTimes++;
      }
    }
  })
  intersectionObserver.observe(loadMoreRef.value);
})
onBeforeUnmount(() => {
  intersectionObserver.disconnect()
})
</script>
<style lang="scss">
.load-more {
  padding: 40px 0 20px 0;
  >.icon {
    >i {
      $size: 16px;
      display: inline-block;
      font-size: $size;
      width: $size;
      height: $size;
      text-align: center;
      line-height: $size;
      animation: rotate-icon 3s linear infinite reverse;
      margin-right: 5px;
    }
  }
  > div {
    width: fit-content;
    margin: auto;
    padding: 5px 15px;
  }
  >.load {
    background: var(--background-color-linear-tag);
    border-radius: 100px;
    cursor: pointer;
    color: #fff;
  }
}
</style>

没错,这就是本博客当前实现无限加载的方法。

赞 3
收藏
分享

本作品系 原创,作者:你不熟悉的x先生

原文链接:https://shiniest.cn/blog/article/157

文本版权:文本版权归作者所有

转载需著名并注明出处(禁止商业使用)

评论和回复

0/500
    没有更多啦~
    怎么一条数据都没有呢?
简介
当一个 IntersectionObserver 对象被创建时,其被配置为监听根中一段给定比例的可见区域。一旦 IntersectionObserver 被创建,则无法更改其配置,所以一个给定的观察者对象只能用来监听可见区域的特定变化值;然而,你可以在同一个观察者对象中配置监听多个目标元素。
目录
推荐阅读

D&D By x先生 With