列表滚动加载实现

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

大功告成! 撒花🎉🎉🎉

相关推荐
Martin -Tang19 分钟前
vite和webpack的区别
前端·webpack·node.js·vite
迷途小码农零零发20 分钟前
解锁微前端的优秀库
前端
王解1 小时前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js
老码沉思录1 小时前
写给初学者的React Native 全栈开发实战班
javascript·react native·react.js
我不当帕鲁谁当帕鲁1 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
那一抹阳光多灿烂1 小时前
工程化实战内功修炼测试题
前端·javascript
放逐者-保持本心,方可放逐2 小时前
微信小程序=》基础=》常见问题=》性能总结
前端·微信小程序·小程序·前端框架
毋若成4 小时前
前端三大组件之CSS,三大选择器,游戏网页仿写
前端·css
红中马喽4 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习
Black蜡笔小新5 小时前
网页直播/点播播放器EasyPlayer.js播放器OffscreenCanvas这个特性是否需要特殊的环境和硬件支持
前端·javascript·html