在vue中使用vant组件库有个van-pull-refresh下拉组件,配合van-list列表组件实现页面的下拉刷新和上拉加载,原理简单,适用场景在列表页面内容展示。
下拉刷新
PullRefresh 实现下拉刷新的效果。
PullRefresh组件中的searchRefreshing属性,是下拉刷新时专用的,值有两个true/false;
searchRefreshing设置为true,表示下拉刷新完毕,列表顶部的"加载中…"会隐藏;
searchRefreshing设置为false,表示正在下拉刷新,列表顶部的"加载中…"会显示
参数说明
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
v-model | 是否处于加载中状态 | boolean | - |
pulling-text | 下拉过程提示文案 | string | 下拉即可刷新… |
loosing-text | 释放过程提示文案 | string | 释放即可刷新… |
loading-text | 加载过程提示文案 | string | 加载中… |
success-text | 刷新成功提示文案 | string | - |
success-duration | 刷新成功提示展示时长(ms) | number或 string | 500 |
animation-duration | 动画时长 | number或 string | 300 |
head-height | 顶部内容高度 | number 或 string | 50 |
pull-distance | 触发下拉刷新的距离 | number 或 string | 与 head-height 一致 |
disabled | 指是否禁用下拉刷新 | boolean | false |
事件说明
事件名 | 说明 | 回调参数 |
---|---|---|
refresh | 下拉刷新时触发 | - |
change | 拖动时或状态改变时触发 | { status: string, distance: number } |
插槽说明
名称 | 说明 | 参数 |
---|---|---|
default | 自定义内容 | - |
normal | 非下拉状态时顶部内容 | - |
pulling | 下拉过程中顶部内容 | { distance: number } |
loosing | 释放过程中顶部内容 | { distance: number } |
loading | 加载过程中顶部内容 | { distance: number } |
success | 刷新成功提示内容 | - |
上拉加载
List 组件实现上拉加载的效果
List通过loading和finished两个变量控制加载状态,当组件滚动到底部时,会触发load事件并将loading设置成true。此时可以发起异步操作并更新数据,数据更新完毕后,将loading设置成false即可。若数据已全部加载完毕,则直接将finished设置成true即可。
注意事项:
- v-model : 是否处于加载状态,加载过程中不触发load事件
- finished: 是否已加载完成,加载完成后不再触发load事件
- offset : 滚动条与底部距离小于 offset 时触发load事件
- loading-text加载过程中的提示文字
- finished-text加载完成后的提示文字
List有以下三种状态,理解这些状态有助于你正确地使用List组件:
- 非加载中,loading为false,此时会根据列表滚动位置判断是否触发load事件(列表内容不足一屏幕时,会直接触发)
- 加载中,loading为true,表示正在发送异步请求,此时不会触发load事件
- 加载完成,finished为true,此时不会触发load事件
在每次请求完毕后,需要手动将loading设置为false,表示加载结束
事件使用:@load方法
滚动条与底部距离小于 offset 时触发
属性说明
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
v-model:loading | 是否处于加载状态,加载过程中不触发 load 事件 | boolean | false |
v-model:error | 是否加载失败,加载失败后点击错误提示可以重新触发 load 事件 | boolean | false |
finished | 是否已加载完成,加载完成后不再触发 load 事件 | boolean | false |
offset | 滚动条与底部距离小于 offset 时触发 load 事件 | number& string | 300 |
loading-text | 加载过程中的提示文案 | string | 加载中… |
finished-text | 加载完成后的提示文案 | string | - |
error-text | 加载失败后的提示文案 | string | - |
immediate-check | 是否在初始化时立即执行滚动位置检查 | boolean | true |
disabled | 是否禁用滚动加载 | boolean | false |
direction | 滚动触发加载的方向,可选值为 up | string | down |
scroller v4.6.4 | 指定需要监听滚动事件的节点,默认为最近的父级滚动节点 | Element | - |
事件
事件名 | 说明 | 回调参数 |
---|---|---|
load | 滚动条与底部距离小于 offset 时触发 | - |
方法
方法名 | 说明 | 参数 | 返回值 |
---|---|---|---|
check | 检查当前的滚动位置,若已滚动至底部,则会触发 load 事件 | - | - |
完整代码示例
<template><div><div v-if="listArr.length > 0"><PullRefresh v-model="isLoading" @refresh="handleRefresh"><Listv-model:loading="loading":finished="finishedStatus":offset="80"finished-text="没有更多了"@load="handleLoad"error-text="请求失败,点击重新加载":scroller="scrollerBody":immediate-check="false"><CellGroup v-for="item in listArr" style="margin-bottom: 10px" :key="item.id" inset border><Cell><template #title><span class="custom-title">条码号: </span><span>{{ item.packageCode }}</span></template></Cell><div class="contentDesc"><div class="entryDesc"><span>需求来源:</span><span>{{ item.receiveCode }}</span></div><div class="entryDesc"><span>激活状态:</span><span>{{ item.printStatus_dictText }}</span></div><div class="entryDesc"><span>单号:</span><span>{{ item.skuCode }}</span></div><div class="entryDesc"><span>打印日期:</span><span>{{ item.printDate }}</span></div></div></CellGroup></List></PullRefresh></div></div>
</template>
<script lang="ts">import { defineComponent, ref, onMounted, computed, reactive, toRefs } from 'vue';import { Icon, Divider, Row, Cell, CellGroup, Dialog, Button, Picker, Field, Calendar, Form, PullRefresh, List, Popup } from 'vant';import 'vant/lib/index.css';import { PrintCode, PagePrintCode } from './print.data';import { QrCode } from '/@/components/Qrcode/index';import { useRouter, useRoute } from 'vue-router';import { list } from '/@/views/wcs/PrintCodeList/PrintCode.api';export default defineComponent({// 若需要开启页面缓存,请将此参数跟菜单名保持一致name: 'LargePackageCode',components: {Icon,Divider,Cell,CellGroup,Picker,Calendar,Field,Form,Button,PullRefresh,List,Dialog,QrCode,Popup,Row,},setup() {const { replace } = useRouter();const route = useRoute();let isLoading = ref<boolean>(false);let loading = ref<boolean>(false);let finishedStatus = ref<boolean>(false);let listArr = ref<PrintCode[]>([{}]);let pageNo = ref<number>(1);let pageSize = ref<number>(10);let totalItems = ref<number>(0);let showDialog = ref(false);const state = reactive({receiveCode: '',});onMounted(() => {listArr.value = [];getInfo('');});const scrollerBody = computed(() => {return document.body;});async function getInfo(status) {let data: PagePrintCode = await list({pushDate: '', // 推送日期 query falsereceiveCode: state.receiveCode, // 收货单号 query falsestatus: status, // 状态pageNo: pageNo.value, // pageNo,示例值(1) query falsepageSize: pageSize.value, // pageSize,示例值(10) query falsecolumn: 'createTime',order: 'desc',});totalItems.value = data.total as 0;let arr = data.records as [];listArr.value = listArr.value.concat(arr);loading.value = false;const num = listArr.value.length - totalItems.value;if (num >= 0) {finishedStatus.value = true;}}async function handleRefresh() {pageNo.value = 1;isLoading.value = false;await getInfo('');// 清空列表数据finishedStatus.value = false;}function handleLoad() {// loading.value = true;setTimeout(() => {if (isLoading.value) {listArr.value = [];isLoading.value = false;}// 数据全部加载完成pageNo.value++;getInfo('');});}return {...toRefs(state),listArr,totalItems,isLoading,loading,finishedStatus,showDialog,handleRefresh,handleLoad,scrollerBody,};},});
</script>
<style lang="less" scoped>.contentDesc {padding: 10px 16px;color: #969799;.entryDesc {display: flex;justify-content: space-between;padding: 2px;align-items: center;}}
</style>
bug
在@load事件不生效,在滚动的过程中,onLoad事件没有任何反应,项目中vant版本 “vant”: “^4.9.1”
若不设置要设置父元素css属性 style=“{height: 100vh; over; overflow-y: scroll;}”,但是这样设置会有2个滚动条,一个是List父元素的,一个是body的,很难看
这个时候就考虑scroller属性,指定需要监听滚动事件的节点到body元素上,这时就会只出现一个滚动条,onLoad事件也触发了。
// template 中设置
<Listv-model:loading="loading":finished="finishedStatus":offset="80"finished-text="没有更多了"@load="handleLoad"error-text="请求失败,点击重新加载":scroller="scrollerBody":immediate-check="false" >// :immediate-check="false" 设置首次不加载....</List>
// ts中设置const scrollerBody = computed(() => {return document.body;});