列表滚动加载实现

👻:我们在日常开发当中"滚动加载数据"是我们经常会遇到的一种列表请求方式,本篇文章将采用浏览器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>

大功告成! 撒花🎉🎉🎉

相关推荐
放逐者-保持本心,方可放逐5 分钟前
webgl(three.js 与 cesium 等实例应用)之浏览器渲染应用及内存释放的关联与应用
开发语言·javascript·webgl·顶点着色器·three.js 释放·cesium 释放·片元着色器
行云流水62634 分钟前
js实现输入高亮@和#后面的内容
前端·javascript·css
涛哥码咖1 小时前
前端十种排序算法解析
前端·算法·排序算法
村头的猫1 小时前
建站SEO优化之站点地图sitemap
前端·经验分享·笔记
Sui_Network1 小时前
WAYE.ai 为Sui 上 AI 的下一个时代赋能
大数据·前端·人工智能·物联网·游戏
掘金安东尼2 小时前
换了无数键盘、工学椅,却从没认真选过一块为程序员“注意力”设计的屏
前端·面试·github
戒不掉的伤怀2 小时前
react实现axios 的简单封装
javascript·react.js·ecmascript
Bigger2 小时前
🍸 Apple Liquid Glass 设计理念与前端实现解析
前端·css·apple
星火飞码iFlyCode2 小时前
【无标题】
java·前端·人工智能·算法
夏梦春蝉2 小时前
ES6从入门到精通:变量
前端·javascript·es6