vue|vue3 骨架屏+上拉加载更多封装

vue3 骨架屏+上拉加载更多封装

  • 介绍
    因业务需求要用到滚动加载,就用到了vant组件库里的List组件,然后突发奇想封装了个骨架屏进去,api和使用方法还有文档都参考了vant的list组件,不过没有参考源码,此组件是我第一次封装,比较贴合自身业务,所以不太符合需求的同学可以直接修改源码使用,感谢vant团队!vant的List组件地址 (https://vant-contrib.gitee.io/vant/v3/#/zh-CN/list)
    提供骨架屏展示、瀑布流滚动加载,用于展示长列表,当列表即将滚动到底部时,会触发事件并加载更多列表项。
  • 效果

  • 引入
import ListView from '@/components/list_view/list_view.vue' components:{ ListView }

  • 代码演示
    – 用法
vue|vue3 骨架屏+上拉加载更多封装
文章图片
class="name"> 联系人: {{ item.concact_name }} class="time"> 填写时间: {{ item.collection_time }}
编辑

='ts'> import { defineComponent, reactive, toRefs } from "vue"; import ListView from "@/components/list_view/list_view.vue"; export default defineComponent({ name: "", components: { ListView, }, setup() { const state = reactive({ list: [], showLoading: true, showError: false, finished: false }); // 设置骨架屏所用到的数据模板,主要用于撑开span标签 const emptyItem = { full_photo: "", concact_name: "asdasd", collection_time: "2021-3-3 15:23", }; //绑定一个可滑动的容器,默认情况下是window,也就是浏览器的默认滑动 // 如果限定列表是在某一个元素内滑动,就需要把这个可滑动的元素传入ListView组件 // 用来绑定滑动事件,如果没有不传就好了 const routerView = document.querySelector(".router_view"); const requestData = https://www.it610.com/article/() => { // 异步更新数据 // setTimeout 仅做示例,真实场景中一般为 ajax 请求 setTimeout(() => { for (let i = 0; i < 10; i++) { state.list.push({ full_photo:"http://static.feidaojixie.com/machine/51271/full_photo/e9532332299e357ab815373a145f8ce2", concact_name: "联系人" + (state.list.length + 1), collection_time: "2021-3-3 15:23", }); } // 加载状态结束 state.showLoading = false; // 数据全部加载完成 if (state.list.length >= 40) { state.finished = true; } }, 3000); }; return { ...toRefs(state), emptyItem, routerView, requestData, }; }, });

  • API
    • Props
参数 说明 类型 默认值
list-data 数据数组 Array []
bind-key vue的for循环绑定的key String,Function 默认值为index
v-model:loading 是否处于加载状态,加载过程中不触发 load 事件 Boolean false
v-model:error 是否加载失败,加载失败后点击错误提示可
以重新触发 load 事件 boolean false
finished 是否已加载完成,加载完成后不再触发 load 事件 Boolean false
loading-text 加载过程中的提示文案 String 加载中…
finished-text 加载完成后的提示文案 String 没有更多了…
error-text 加载失败后的提示文案 String 加载失败了,点我重新加载
empty-text 数据为空时的提示文案 String 暂无数据
immediate-check 是否在初始化时立即执行滚动位置检查 Boolean true
empty-item 设置骨架屏所用到的数据模板,主要用于撑开元素标签 Object {}
bind-scroll-document 列表所在的可滑动的容器,默认为window Object window
  • Events
事件名 说明 回调参数
load 滚动条与底部距离小于 offset 时触发 -
  • Slots
名称 说明
default 列表内容
loading 自定义底部加载中提示
finished 自定义底部加载完成提示
error 自定义底部加载失败提示
empty 自定义列表数据为空提示
问题
  • 骨架屏使用什么实现?
    骨架屏是通过css样式给子项中的img和span、a标签设置背景色来实现的,所以需要传递 empty-item 参数来撑起列表元素的span和a标签,如果你还使用了其他标签,可以参考源码中css样式添加其他标签
  • List 的运行机制是什么?
    List 会监听浏览器或目标元素的滚动事件并计算列表的位置,当列表底部与可视区域的距离小于 offset 时,List 会触发一次 load 事件。
  • 【vue|vue3 骨架屏+上拉加载更多封装】loading 和 finished 分别是什么含义?
    List 有以下五种状态,理解这些状态有助于你正确地使用 List 组件:
    1. init,初始化加载中,当loading为true且listData长度为0时,为init状态,此时显示骨架屏
    2. 非加载中,loading 为 false,此时会根据列表滚动位置判断是否触发 load 事件
    3. 加载中,loading 为 true,表示正在发送异步请求,此时不会触发 load 事件
    4. 加载完成,finished 为 true且listData长度不为0,此时不会触发 load 事件
    5. 暂无数据,finished为true,loading为false,finished 为true
      在每次请求完毕后,需要手动将 loading 设置为 false,表示加载结束
全部代码
.list-view-init-view { pointer-events: none; } .list-view-empty-view span, .list-view-empty-view a { color: rgba(0, 0, 0, 0) !important; border-radius: 2px; background: linear-gradient( -45deg, #999999 0%, #777 25%, #999999 50%, #777 75%, #999999 100% ); animation: gradientBG 4s ease infinite; background-size: 400% 400%; } /* [src=""],img:not([src])*/ .list-view-empty-view img { content: url(./no_url.png); background: linear-gradient( -45deg, #999999 0%, #777 25%, #999999 50%, #777 75%, #999999 100% ); animation: gradientBG 4s ease infinite; background-size: 400% 400%; } @keyframes gradientBG { 0% { background-position: 100% 100%; } 50% { background-position: 0% 0%; } 100% { background-position: 100% 100%; }}.fade-enter-active, .fade-leave-active { transition: opacity .4s ease }.fade-enter-from, .fade-leave-to { opacity: 0.5 }.list-view-center{ display: flex; flex-direction: row; align-items: center; justify-content: center; padding: 20px; color: #777; font-size: 15px; }

    推荐阅读