vue3 + vant移动端实现上拉刷新下拉加载

介绍

在移动端开发中,下拉刷新、上拉加载是列表类页面的核心交互需求。这里使用vant UI框架van-pull-refresh + van-list组件来实现这功能。

官网地址:https://vant.pro/vant/#/zh-CN/

核心原理

  1. 下拉刷新(van-pull-refresh):监听用户下拉手势,触发刷新逻辑,重置列表数据为第一页,完成后恢复初始状态。
  2. 上拉加载(van-list): 监听滚动容器触底事件,触发加载逻辑,加载下一页数据,直到无更多数据。
  3. 状态管理:通过loading(加载中)、finished(加载完成)、refreshing(刷新中)三个状态控制组件交互,避免重复请求。

上拉加载下拉刷新组件

页面结构

javascript 复制代码
<template>
  <van-pull-refresh
    v-model="refreshing"
    @refresh="onRefresh"
  >
    <van-list
      v-model:loading="loading"
      :finished="finished"
      :finished-text="list.length === 0 ? '' : '没有更多了'"
      @load="onLoad"
      :immediate-check="false"
    >
      <slot :list="list"></slot>
    </van-list>
  </van-pull-refresh>
</template>
<script lang="ts" setup> 
const props = defineProps({
  api: {
    type: Function,
    required: true
  },
  // 每页条数
  pageSize: {
    type: Number,
    default: 10
  }
})
const emit = defineEmits(['update:list', 'refresh'])
// 状态
const list = ref<any>([])
const pageNo = ref(1)
const loading = ref(false)
const refreshing = ref(false)
const finished = ref(false)

// 重置 & 刷新
const onRefresh = async () => {
  console.log('refresh')
  loading.value = true
  pageNo.value = 1
  finished.value = false
  try {
    await fetchData()
  } finally {
    console.log('结束+++++');
    setTimeout(() => {
      refreshing.value = false
      loading.value = false
    }, 300)
  }
  emit('refresh')
}

// 上拉加载
const onLoad = async () => {
  console.log('load')
  if (refreshing.value) return
  pageNo.value++
  await fetchData()
}

// 请求数据
const fetchData = async () => {
  try {
    const res = await props.api({
      pageNo: pageNo.value,
      pageSize: props.pageSize
    })

    if (pageNo.value === 1) {
      list.value = res.list || []
    } else {
      list.value = [...list.value, ...(res.list || [])]
    }

    // 判断是否加载完
    finished.value = list.value.length >= (res.total || 0)
  } catch(error) {
    if (pageNo.value === 1) {
      refreshing.value = false
    }
  } finally {
    loading.value = false
    emit('update:list', list.value);
  }
}

// 外部强制刷新用
const reload = async () => {
  pageNo.value = 1
  finished.value = false
  list.value = []
  await fetchData()
}

defineExpose({ reload, list })

// 初始化
fetchData()
</script>
<style lang="scss" scoped></style>

配置型

配置项 作用 推荐值
immediate-check 是否初始化时立即检测触底 false(避免页面加载时误触底)
offset 触底检测偏移量(距离底部多少像素触发加载) 100(增大偏移量减少误触)
disabled(pull-refresh) 刷新时禁用加载 绑定 loading(避免刷新和加载同时触发)

组件使用

javascript 复制代码
<RefreshList ref="refreshListRef" :api="getData">
  <template #default="{ list }">
  // 列表数据
  </template>
</RefreshList>
<script lang="ts" setup>
const getData = async ({ pageNo, pageSize }) => {
  try {
    const result = await getList({ ...formData, pageNo, pageSize })
    return {
      list: result.list,
      total: result.total
    }
  } catch (error) {
    console.log(error)
  }
}
</script>

可拖拽数据大屏项目地址

react版本:https://gitee.com/qlsgr/DataReport/

vue版本:https://gitee.com/belief-team/report

相关推荐
阿丰资源10 小时前
SpringBoot+Vue实战:打造企业级在线文档管理系统
vue.js·spring boot·后端
忆往wu前11 小时前
从0到1一步步拆解搭建,梳理一个 Vue3 简易图书后台全开发流程
前端·javascript·vue.js
光影少年12 小时前
大屏页面,一次多个请求,请求加密导致 点击 全局时间选择器 时出现卡顿咋解决(面板收起会延迟1~2秒)
前端·javascript·vue.js·学习·前端框架·echarts·reactjs
Mr.mjw12 小时前
vue中封装一个环形进度条组件,根据外部盒子大小自适应变化
前端·javascript·vue.js
唯火锅不可辜负12 小时前
uniapp开发公众号订阅功能踩坑小记
前端·vue.js
像我这样帅的人丶你还13 小时前
前端监控体系与实践(二):全局监控
前端·javascript·vue.js
前端那点事13 小时前
Vue3 超全复盘!30+前端高频核心知识点(开发+面试全覆盖)
前端·vue.js
FlyWIHTSKY14 小时前
Vue 3 中 RouteRecord 详解(Vue Router 4)
前端·javascript·vue.js
@菜菜_达15 小时前
Vue生命周期
前端·javascript·vue.js
前端那点事15 小时前
Vue线上代码调试全攻略(安全无侵入,新手也能上手)
前端·vue.js