vue3.0 + vant实现下拉刷新上拉加载

在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或 string500
animation-duration动画时长number或 string300
head-height顶部内容高度number 或 string50
pull-distance触发下拉刷新的距离number 或 string与 head-height 一致
disabled指是否禁用下拉刷新booleanfalse

事件说明

事件名说明回调参数
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组件:

  1. 非加载中,loading为false,此时会根据列表滚动位置判断是否触发load事件(列表内容不足一屏幕时,会直接触发)
  2. 加载中,loading为true,表示正在发送异步请求,此时不会触发load事件
  3. 加载完成,finished为true,此时不会触发load事件

在每次请求完毕后,需要手动将loading设置为false,表示加载结束
事件使用:@load方法
滚动条与底部距离小于 offset 时触发
属性说明

参数说明类型默认值
v-model:loading是否处于加载状态,加载过程中不触发 load 事件booleanfalse
v-model:error是否加载失败,加载失败后点击错误提示可以重新触发 load 事件booleanfalse
finished是否已加载完成,加载完成后不再触发 load 事件booleanfalse
offset滚动条与底部距离小于 offset 时触发 load 事件number& string300
loading-text加载过程中的提示文案string加载中…
finished-text加载完成后的提示文案string-
error-text加载失败后的提示文案string-
immediate-check是否在初始化时立即执行滚动位置检查booleantrue
disabled是否禁用滚动加载booleanfalse
direction滚动触发加载的方向,可选值为 upstringdown
scroller v4.6.4指定需要监听滚动事件的节点,默认为最近的父级滚动节点Element-

事件

事件名说明回调参数
load滚动条与底部距离小于 offset 时触发-

方法

方法名说明参数返回值
check检查当前的滚动位置,若已滚动至底部,则会触发 load 事件--

完整代码示例

<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">条码号:&nbsp;</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事件也触发了。

// 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;
 });
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以通过使用Vant组件库和Vue 3来实现上拉分页和下拉刷新功能。下面是一个简单的示例代码: 首先,您需要安装Vant组件库。可以通过npm或yarn来安装。 ```bash npm install vant ``` 在Vue文件中,您需要引入Vant组件并注册使用它们。在需要使用上拉分页和下拉刷新的页面中,您可以使用Vant的`PullRefresh`和`List`组件实现。 ```vue <template> <div> <van-pull-refresh v-model="refreshing" @refresh="onRefresh"> <van-list v-model="loading" :finished="finished" @load="onLoad"> <!-- 这里是列表内容 --> <van-list-item v-for="item in list" :key="item.id">{{ item.text }}</van-list-item> </van-list> </van-pull-refresh> </div> </template> <script> import { ref, reactive } from 'vue'; export default { setup() { // 列表数据 const list = reactive([]); // 是否正在刷新 const refreshing = ref(false); // 是否正在加载更多数据 const loading = ref(false); // 是否已加载完所有数据 const finished = ref(false); // 模拟异步获取数据 const fetchData = () => { return new Promise((resolve) => { setTimeout(() => { resolve([ { id: 1, text: 'item 1' }, { id: 2, text: 'item 2' }, { id: 3, text: 'item 3' }, ]); }, 1000); }); }; // 下拉刷新事件 const onRefresh = () => { refreshing.value = true; // 模拟异步获取最新数据 fetchData().then((data) => { list.splice(0, list.length, ...data); refreshing.value = false; finished.value = false; }); }; // 上拉加载更多事件 const onLoad = () => { loading.value = true; // 模拟异步加载更多数据 fetchData().then((data) => { if (data.length > 0) { list.push(...data); } else { finished.value = true; } loading.value = false; }); }; return { list, refreshing, loading, finished, onRefresh, onLoad, }; }, }; </script> ``` 在上述代码中,我们通过`van-pull-refresh`组件实现下拉刷新功能,并通过`van-list`组件实现分页加载功能。当页面触发下拉刷新事件时,我们可以通过异步获取最新数据并更新列表。当页面触发上拉加载更多事件时,我们可以通过异步加载更多数据并追加到列表末尾。 这样,您就可以使用Vant和Vue 3来实现上拉分页和下拉刷新功能了。希望对您有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值