列表滚动加载实现

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

大功告成! 撒花🎉🎉🎉

相关推荐
独立开阀者_FwtCoder几秒前
"页面白屏了?别慌!前端工程师必备的排查技巧和面试攻略"
java·前端·javascript
慧一居士1 分钟前
Vite 完整功能详解与 Vue 项目实战指南
前端·vue.js
南岸月明1 分钟前
不聊主业,聊聊你们眼中的副业是什么样的?
前端
Kevin在掘金920146 分钟前
c#、.net、Fluent UI Blazor
前端
LovelyAqaurius7 分钟前
RSA加密算法:从数学魔法到现实守护
前端
Hilaku8 分钟前
说实话,React的开发体验,已经被Vue甩开几条街了
前端·javascript·vue.js
星语卿8 分钟前
Js事件循环
javascript
datagear9 分钟前
如何在DataGear 5.4.1 中快速制作HTTP数据源服务端分页的数据表格看板
javascript·数据可视化
蛋黄蛋黄12 分钟前
微信表情怎么在自己的项目使用微信表情?-> [开源仓库]wechat-emoji
前端·github
汪子熙13 分钟前
错误剖析:net::ERR_HTTP2_PROTOCOL_ERROR 200 (OK) 的含义与解决之道
前端