列表滚动加载实现

👻:我们在日常开发当中"滚动加载数据"是我们经常会遇到的一种列表请求方式,本篇文章将采用浏览器IntersectionObserver API来实现懒加载的请求效果👇👇

Intersection Observer

它是浏览器提供的一种观察者API,提供了一种异步观察目标元素与祖先元素或顶级文档视口的交集变化的方法。

Intersection Observer API 允许代码注册一个回调函数,只要他们希望监视的元素进入或退出另一个元素(或视口),或者当两者相交的数量改变请求的数量时,就会执行该回调函数。这样,站点就不再需要在主线程上做任何事情来监视这种元素交叉点,并且浏览器可以根据需要自由地优化交叉点的管理。

Intersection Observer API 无法告诉您的一件事:重叠像素的确切数量或具体是哪些像素;然而,它涵盖了更常见的用例"如果它们相交大约N %,我需要做一些事情。"

简单一点来讲就是,浏览器可以帮我们监视一个元素和它所在的祖先元素的重叠比例,提供了一个回调函数的入口,方便我们在任意交叉时间节点去做一些事。👀👀

实现原理

那我们如何利用这个特性来实现滚动加载呢?(❁´◡`❁)

例如下面的列表想要在红色框内实现滚动加载,我们可以在列表下方添加一个高度为0的div的节点(图中黄色框所示),监测这个空白节点是否滚动出现在父容器当中,也就是与父元素产生了视口交集(出现在了父元素的底部),这个时候我们就可以通过回调函数调接口,增加列表长度;

每一次空白div元素出现在父容器,被我们可视视口捕捉到时,调用数据请求接口,实现滚动加载效果,直至列表数据的返回长度小于指定长度(也就是下一次调用接口就没有数据了)😎

代码实现

在Vue3中的具体实现,结合了vueuse库,使用之前记得install一下库👇👇

xml 复制代码
<script setup lang="ts">
import { useIntersectionObserver } from '@vueuse/core'
​
const deployList = ref<DeployType[]>([]),  //列表数据
      pageParams = reactive({
          pageNo: 1,
          pageSize: 10
      })
const target = ref()  //目标节点
const isLazy = ref(false) //是否懒加载
const isLazyEnd = ref(false) //是否懒加载结束
​
//使用vueuse库中封装好的IntersectionObserver
useIntersectionObserver(target, ([{ isIntersecting }]) => {
  if (isIntersecting) {
    // if (isLazyEnd.value) {
    //   stop()
    // }
    isLazy.value = true
  }
})
//进行监听
watch(
  () => isLazy.value,
  () => {
    if (isLazy.value && !isLazyEnd.value) {
      //如果触发了懒加载,更新数据
      pageParams.pageNo++
      //发起请求
      $api.getDeployList(pageParams).then(res => {
        if (res.data.rows.length < pageParams.pageSize) {
          // 如果返回的数据小于每页的数据,说明已经到底了,下次请求就没有数据了
          isLazyEnd.value = true
        }
        deployList.value.push(...res.data.rows)
      })
      isLazy.value = false
    }
  }
)
// ---------------------- 懒加载请求标志  end----------------------
​
</script>
<template>
    <VCard class="text-left container">
      <el-container>
        <el-aside width="500px" class="aside">
          <el-timeline>
            <el-timeline-item
              v-for="item in deployList"
              :key="item.id"
              :timestamp="item.createdAt"
              placement="top"
            >
              xxxx
            </el-timeline-item>
          </el-timeline>
          <div v-if="deployList.length > 9" ref="target"></div>
        </el-aside>
        <el-main>
          xxxx
        </el-main>
      </el-container>
    </VCard>
</template>

大功告成! 撒花🎉🎉🎉

相关推荐
CharlesYu0110 小时前
前端性能优化的第一性原理,是不断缩短“用户发起意图 → 获得可用结果”之间的时间
前端
Bs_MoneyMagnet10 小时前
基于springboot+vue的医疗健康便民服务平台的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring
平头哥技术团队10 小时前
Day 21 _ 页内锚点_给每段起个 id,目录写 href=_#id_,点一下页面就滚到那一段
前端·html·html5
子兮曰11 小时前
Bun v1.4.1 深度解析:从 Zig 到 Rust,一场 11 天、64 个 AI 代理的语言迁徙
前端·后端·bun
人民广场吃泡面12 小时前
什么是AI Agent?它又能给前端带来哪些效率提升?
前端·人工智能
中科三方12 小时前
两家域名注册商资质被ICANN终止:企业域名资产安全再受关注
前端·网络·安全·域名
bug总结12 小时前
uniapp vue3全局方法注册使用
前端·javascript·uni-app
华无丽言13 小时前
如何在宜搭中实现获取子表中的字段值赋值到父表中?
前端·javascript·低代码
IT_陈寒13 小时前
Vue的computed属性竟然坑了我一把
前端·人工智能·后端
威斯软科的老司机13 小时前
通俗讲解 CNN 图像识别、向量 Embedding、Softmax 概率计算这三块的简化原理
前端·人工智能·ui·数字孪生