在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 事件 | - | - |
完整代码示例
cpp
<template>
<div>
<div v-if="listArr.length > 0">
<PullRefresh v-model="isLoading" @refresh="handleRefresh">
<List
v-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 false
receiveCode: state.receiveCode, // 收货单号 query false
status: status, // 状态
pageNo: pageNo.value, // pageNo,示例值(1) query false
pageSize: pageSize.value, // pageSize,示例值(10) query false
column: '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事件也触发了。
cpp
// template 中设置
<List
v-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;
});