列表滚动加载实现

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

大功告成! 撒花🎉🎉🎉

相关推荐
东风破_4 小时前
React 受控组件与非受控组件:从一个输入框讲清表单数据流
前端
尤乐娃子4 小时前
进入大厂(厂子大)实习Day12
前端·笔记·实习
程序员爱钓鱼4 小时前
Rust Copy详解:隐式复制与轻量数据类型
前端·后端·rust
四六的六6 小时前
端侧模型多端部署实战:从格式转换到灰度发布,Web 和移动端统一部署流水线
前端·人工智能·大模型·ai编程·ai模型·ai产品·端侧ai
vx-程序开发7 小时前
springboot农产品运输服务平台---附源码75498
java·javascript·spring boot·python·eclipse·django·php
独隅8 小时前
前端离线暂停更新策略:Service Worker 与 PWA 的静默控制实践
前端
妙码生花8 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(五十八):后台系统配置管理实现
前端·后端·go
用户938515635078 小时前
React 受控/非受控组件与 React.memo 性能优化——从本质到实战
前端·javascript·react.js
IT_陈寒8 小时前
Java并行流把我坑惨了:原来不是线程安全的!
前端·人工智能·后端