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

相关推荐
cch891818 小时前
易语言VS VUE:编程工具终极对决
前端·javascript·vue.js
一 乐18 小时前
鲜花商城|基于springboot + vue鲜花商城系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·鲜花商城系统
IT东19 小时前
Vue 多环境部署全解析:解决测试与生产一致性难题
前端·javascript·vue.js
布局呆星21 小时前
Vue3 计算属性|从基础缓存到可读写
前端·javascript·vue.js
蓝莓味的口香糖1 天前
【vue】初始化 Vue 项目
前端·javascript·vue.js
QQ5110082851 天前
基于区块链的个人医疗咨询挂号信息系统vue
前端·vue.js·区块链
阿琳a_2 天前
在github上部署个人的vitepress文档网站
前端·vue.js·github·网站搭建·cesium
Zk.Sun2 天前
【RK3588 Mali610 适配 Qt6 】
前端·javascript·vue.js
不想吃菠萝2 天前
vue3+ts 使用postcss-pxtorem依赖进行rem适配
前端·javascript·vue.js·postcss
Rysxt_2 天前
Vue 组件穿透(透传)完全指南:从背景到实战
前端·javascript·vue.js