微信小程序uni-app+vue3实现局部上下拉刷新和scroll-view动态高度计算

news2025/2/28 19:40:21

微信小程序uni-app+vue3实现局部上下拉刷新和scroll-view动态高度计算

前言

在uni-app+vue3项目开发中,经常需要实现列表的局部上下拉刷新功能。由于网上相关教程较少且比较零散,本文将详细介绍如何使用scroll-view组件实现这一功能,包括动态高度计算、下拉刷新、上拉加载等完整实现。在这里插入图片描述

重要提示

⚠️ triggered状态管理是关键

  • triggered必须手动管理其true/false状态
  • 不正确的状态管理会导致下拉刷新卡住
  • 需要在适当的时机重置状态

核心实现思路

  1. 状态定义
// 下拉刷新相关状态
const triggered = ref(false)                 // 触发下拉刷新状态
const refresherEnabled = ref(true)           // 是否启用下拉刷新
  1. 关键事件处理
// 下拉过程中触发
const onPulling = () => {
  triggered.value = true  // 手动设置为true
}

// 刷新结束时触发
const onRestore = () => {
  triggered.value = false  // 手动重置为false
}

// 刷新中断时触发
const onAbort = () => {
  triggered.value = false  // 手动重置为false
}

// 刷新数据处理
const refreshHistoryList = async () => {
  triggered.value = true  // 开始刷新时设置为true
  try {
    // 执行刷新逻辑
    await loadData()
  } catch (err) {
    console.error('刷新失败:', err)
  } finally {
    triggered.value = false  // 完成后一定要设置为false
  }
}
  1. 组件配置
<scroll-view
  :refresher-enabled="refresherEnabled"
  :refresher-triggered="triggered"
  @refresherrefresh="refreshHistoryList"
  @refresherpulling="onPulling"
  @refresherrestore="onRestore"
  @refresherabort="onAbort"
>
  <!-- 列表内容 -->
</scroll-view>

注意事项

  1. 状态重置时机

    • 刷新完成时必须重置
    • 刷新中断时必须重置
    • 组件卸载时最好重置
  2. 常见问题

    • 忘记重置导致卡住
    • 重置时机不对导致异常
    • 多个事件重复设置状态
  3. 最佳实践

    • 使用try/finally确保重置
    • 统一状态管理位置
    • 添加适当的错误处理

快速开始

1. 基础配置

2. 组件结构

在template中创建scroll-view组件:

<template>
  <scroll-view 
    :style="{ height: scrollViewHeight }"
    :scroll-y="true"
    :refresher-enabled="refresherEnabled"
    @refresherrefresh="refreshHistoryList"
    @refresherpulling="onPulling"
    @scroll="roll"
    :enable-passive="true"
    :show-scrollbar="false"
    @refresherrestore="onRestore"
    @refresherabort="onAbort"
    :refresher-triggered="triggered"
    ref="scrollView"
  >
    <!-- 列表内容 -->
    <view class="empty-state" v-show="!list.length">
      暂无数据
    </view>
    <view v-for="(item, index) in list" :key="index">
      <!-- 列表项内容 -->
    </view>
    <up-loadmore v-if="list.length>0" :status="scrollStatus" @loadmore="loadmore"/>
  </scroll-view>
</template>

注意uwiewPlus组件库up-loadmore是通过@loadmore来触发@click的效果的。

3. 核心状态定义

属性/事件类型默认值必填说明
style.heightstring-设置scroll-view高度,不设置无法滚动
scroll-ybooleanfalse是否允许纵向滚动
scroll-xbooleanfalse是否允许横向滚动
refresher-enabledbooleanfalse是否开启下拉刷新功能
refresher-triggeredbooleanfalse当前下拉刷新状态
enable-passivebooleanfalse是否开启被动监听滚动事件
show-scrollbarbooleantrue是否显示滚动条
@refresherrefreshfunction-下拉刷新触发时的回调
@refresherpullingfunction-下拉过程中触发的回调
@refresherrestorefunction-下拉刷新复位时触发的回调
@refresherabortfunction-下拉刷新被中止时触发的回调
@scrollfunction-滚动时触发的回调函数
refstring-组件的引用标识
// 下拉刷新相关
const triggered = ref(false)                 // 触发下拉刷新状态
const refresherEnabled = ref(true)           // 是否启用下拉刷新
const currentScrollTop = ref(0)              // 当前滚动位置
const scrollViewHeight = ref('400rpx')       // scroll-view高度

// 分页相关
const currentPage = ref(1)                   // 当前页码
const pageSize = ref(10)                     // 每页数量
const totalPage = ref(0)                     // 总页数
const scrollStatus = ref<string>('loadmore') // 滚动状态

4. 动态高度计算

onReady(() => {
  // 获取系统信息
  const systemInfo = uni.getSystemInfoSync()
  const windowHeight = systemInfo.windowHeight
  
  // 获取各元素高度
  const query = uni.createSelectorQuery()
  Promise.all([
    new Promise<number>(resolve => {
      query.select('.u-demo-block').boundingClientRect(data => {
        resolve(data?.height || 0)
      }).exec()
    }),
    // ... 获取其他元素高度
  ]).then(([demoBlockHeight, titleHeight, uploadHeight]) => {
    // 计算scroll-view高度
    const scrollHeight = windowHeight - demoBlockHeight - titleHeight - uploadHeight - 40
    scrollViewHeight.value = `${scrollHeight}rpx`
  })
})

核心功能实现

1. 下拉刷新

// 下拉刷新处理
const refreshHistoryList = async () => {
  triggered.value = true
  currentPage.value = 1
  
  try {
    const res = await loadFirstPage()
    list.value = res.data
    updateLoadStatus()
  } catch (err) {
    console.error('刷新失败:', err)
  } finally {
    triggered.value = false
  }
}

2. 上拉加载

// 上拉加载更多
const loadmore = async () => {
  if (scrollStatus.value === 'noMore') return
  
  scrollStatus.value = 'loading'
  try {
    const res = await loadMoreData(++currentPage.value)
    list.value.push(...res.data)
    updateLoadStatus()
  } catch (err) {
    console.error('加载失败:', err)
    scrollStatus.value = 'loadmore'
  }
}

3. 滚动事件处理

const roll = (e: any) => {
  currentScrollTop.value = e.detail.scrollTop
  
  // 控制下拉刷新启用状态
  refresherEnabled.value = e.detail.scrollTop < 50
  
  // 触底加载更多
  const scrollBottom = e.detail.scrollHeight - e.detail.scrollTop - e.detail.height
  if (scrollBottom < 50 && scrollStatus.value === 'loadmore') {
    loadmore()
  }
}

注意事项

  1. 高度计算

    • 需要考虑所有固定元素的高度
    • 使用rpx单位确保跨设备兼容性
    • 预留适当边距避免内容被遮挡
  2. 性能优化

    • 使用enable-passive提升滚动性能
    • 合理控制刷新频率
    • 避免频繁触发加载更多
  3. 用户体验

    • 添加加载提示
    • 保持滚动位置
    • 合理控制刷新触发时机

加载更多组件使用

⚠️ up-loadmore组件使用说明

  1. 基础配置
<up-loadmore 
  v-if="list.length>0" 
  :status="scrollStatus" 
  @loadmore="loadmore"
  loadmore-text="加载更多"
/>
  1. 状态管理
// 加载状态
const scrollStatus = ref<string>('loadmore') // 可选值: loadmore/loading/noMore

// 加载更多处理
const loadmore = async () => {
  if (scrollStatus.value === 'noMore') return
  
  scrollStatus.value = 'loading'  // 设置加载中状态
  try {
    const res = await loadMoreData(++currentPage.value)
    list.value.push(...res.data)
    
    // 更新加载状态
    if (currentPage.value >= totalPage.value) {
      scrollStatus.value = 'noMore'
    } else {
      scrollStatus.value = 'loadmore'
    }
  } catch (err) {
    console.error('加载失败:', err)
    scrollStatus.value = 'loadmore'
  }
}
  1. 触发方式
  • 通过@loadmore事件监听触发加载
  • 可以在scroll-view滚动到底部时自动触发
  • 也可以点击"加载更多"文本手动触发
  1. 状态说明
  • loadmore: 可以加载更多
  • loading: 正在加载中
  • noMore: 没有更多数据

完整示例

<scroll-view 
  @scroll="roll"
  :scroll-y="true"
>
  <!-- 列表内容 -->
  <view v-for="(item, index) in list" :key="index">
    {{ item }}
  </view>
  
  <!-- 加载更多组件 -->
  <up-loadmore
    v-if="list.length>0"
    :status="scrollStatus"
    @loadmore="loadmore"
    loadmore-text="加载更多"
  />
</scroll-view>

<script setup lang="ts">
const scrollStatus = ref('loadmore')
const currentPage = ref(1)
const list = ref([])

// 滚动触底自动加载
const roll = (e: any) => {
  const scrollBottom = e.detail.scrollHeight - e.detail.scrollTop - e.detail.height
  if (scrollBottom < 50 && scrollStatus.value === 'loadmore') {
    loadmore()
  }
}

// 加载更多处理
const loadmore = async () => {
  if (scrollStatus.value === 'noMore') return
  scrollStatus.value = 'loading'
  
  try {
    const res = await loadMoreData(currentPage.value++)
    list.value.push(...res.data)
    scrollStatus.value = res.hasMore ? 'loadmore' : 'noMore'
  } catch (err) {
    console.error('加载失败:', err)
    scrollStatus.value = 'loadmore'
  }
}
</script>

总结

通过本教程的学习,我们掌握了:

  1. scroll-view组件的基本使用
  2. 动态高度计算方法
  3. 下拉刷新实现
  4. 上拉加载更多功能
  5. 滚动位置维护

参考资料

  • 微信小程序官方文档
  • Vue3文档
    admore’ : ‘noMore’
    } catch (err) {
    console.error(‘加载失败:’, err)
    scrollStatus.value = ‘loadmore’
    }
    }

## 总结

通过本教程的学习,我们掌握了:
1. scroll-view组件的基本使用
2. 动态高度计算方法
3. 下拉刷新实现
4. 上拉加载更多功能
5. 滚动位置维护

## 参考资料
- [微信小程序官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/scroll-view.html)
- [Vue3文档](https://v3.cn.vuejs.org/)
- [uview-plus文档](https://uiadmin.net/uview-plus/) 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2257748.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在Windows和Ubuntu上安装SDKMAN

文章目录 1. SDKMAN概述2. 安装与使用SDKMAN2.1 在Windows上安装SDKMAN2.1.1 安装Git for Windows2.1.2 安装SDKMAN 2.2 利用SDKMAN管理Java2.2.1 查看所有可用的OpenJDK发行版2.2.2 安装Java2.2.3 查看Java版本2.2.4 shell指定使用某个Java版本 2.3 在Ubuntu上安装SDKMAN2.3.1…

1210 作业

思维导图 作业 使用read和write函数拷贝文件&#xff0c;一半拷进一个文件&#xff0c;另一半拷进另一个文件 #include <myhead.h> int main(int argc, const char *argv[]) {int fd1 open("./z1.txt",O_RDONLY);if(fd1-1){perror("open");return…

牛客网热门Java面试题及答案整理(2024最新版)

当今互联网行业中&#xff0c;Java 作为一种广泛应用的编程语言&#xff0c;对于求职者来说仍是一项受欢迎的技能。然而&#xff0c;随着市场上的开发人员数量越来越多&#xff0c;Java 面试的竞争也愈加激烈。 目前 Java 面试有着以下现状&#xff1a; 面试难度加大与过去相…

【SSH+X11】VsCode使用Remote-SSH在远程服务器的docker中打开Rviz

&#x1f680;今天来分享一下通过VsCode的Remote-SSH插件在远程服务器的docker中打开Rviz进行可视化的方法。 具体流程如下图所示&#xff0c;在操作开始前&#xff0c;请先重启设备&#xff0c;排除之前运行配置的影响&#xff1a; ⭐️ 我这里是使用主机连接服务器&#xff…

iPhone 17 Air基本确认,3个大动作

近段时间&#xff0c;果粉圈都在讨论一个尚未发布的新品&#xff1a;iPhone 17 Air&#xff0c;苹果又要来整新活了。 从供应链消息来看&#xff0c;iPhone 17 Air本质上是Plus的替代品&#xff0c;主要是在维持“大屏”这一卖点的同时&#xff0c;增加了“轻薄”属性&#xff…

浅析OCR技术与大模型的深度融合—中安未来OCR产品优势及前景探索

OCR&#xff08;光学字符识别&#xff09;技术作为一种文本识别工具&#xff0c;已在文档管理、自动化办公和图书数字化等领域发挥了重要作用。然而&#xff0c;随着深度学习和大语言模型&#xff08;LLM&#xff09;的迅猛发展&#xff0c;OCR技术迎来了新的机遇和挑战。如今&…

Android四大组件——Activity(二)

一、Activity之间传递消息 在&#xff08;一&#xff09;中&#xff0c;我们把数据作为独立的键值对进行传递&#xff0c;那么现在把多条数据打包成一个对象进行传递&#xff1a; 1.假设有一个User类的对象&#xff0c;我们先使用putExtra进行传递 activity_demo06.xml <…

STM32G4系列MCU双ADC多通道数据转换的应用

目录 概述 1 STM32Cube配置项目 1.1 基本参数配置 1.1.1 ADC1参数配置 1.1.2 ADC2参数配置 1.2 项目软件架构 2 功能实现 2.1 ADC转换初始化 2.2 ADC数据组包 3 测试函数 3.1 Vofa数据接口 3.2 输入数据 4 测试 4.1 ADC1 通道测试 4.2 ADC2 通道测试 概述 本文…

STM32串口接收与发送(关于为什么接收不需要中断而发生需要以及HAL_UART_Transmit和HAL_UART_Transmit_IT的区别)

一、HAL_UART_Transmit和HAL_UART_Transmit_IT的区别 1. HAL_UART_Transmit_IT&#xff08;非阻塞模式&#xff09;&#xff1a; HAL_UART_Transmit_IT 是非阻塞的传输函数&#xff0c;也就是说&#xff0c;当你调用 HAL_UART_Transmit_IT 时&#xff0c;它不会等到数据完全发…

constexpr、const和 #define 的比较

constexpr、const 和 #define 的比较 一、定义常量 constexpr 定义&#xff1a;constexpr用于定义在编译期可求值的常量表达式。示例&#xff1a;constexpr int x 5;这里&#xff0c;x的值在编译期就确定为5。 const 定义&#xff1a;const表示变量在运行期间不能被修改&…

BMS电池管理系统

一.项目简介 1.该项目是基于BQ7692003PWR STM32F103C8T6研发的一块锂电池控制板&#xff0c;本控制板可供五串18650锂电池&#xff08;目前软件仅支持三元锂类型&#xff0c;标称电压为4.2V&#xff09;串联使用&#xff0c;电芯均衡采用被动均衡方式 二.本项目功能 1.监控任…

Milvus向量数据库01-基础概念

Milvus向量数据库01-基础概念 Zilliz Cloud 集群由全托管 Milvus 实例及相关计算资源构成。您可以在 Zilliz Cloud 集群中创建 Collection&#xff0c;然后在 Collection 中插入 Entity。Zilliz Cloud 集群中的 Collection 类似于关系型数据库中的表。Collection 中的 Entity …

【OpenCV】模板匹配

理论 模板匹配是一种在较大图像中搜索和查找模板图像位置的方法。为此&#xff0c;OpenCV 带有一个函数 cv.matchTemplate&#xff08;&#xff09; 。它只是在输入图像上滑动模板图像&#xff08;如在 2D 卷积中&#xff09;&#xff0c;并比较模板图像下的模板和输入图像的补…

深入解析下oracle的number底层存储格式

oracle数据库中&#xff0c;number数据类型用来存储数值数据&#xff0c;它既可以存储负数数值&#xff0c;也可以存储正数数值。相对于其他类型数据&#xff0c;number格式的数据底层存储格式要复杂得多。今天我们就详细探究下oracle的number底层存储格式。 一、环境搭建 1.…

MySQL Binlog 日志监听与 Spring 集成实战

MySQL Binlog 日志监听与 Spring 集成实战 binlog的三种模式 MySQL 的二进制日志&#xff08;binlog&#xff09;有三种常见的格式&#xff1a;Statement 模式、Row 模式和Mixed 模式。每种模式的设计目标不同&#xff0c;适用于不同的场景&#xff0c;以下是它们的详细对比和…

Vmware Vcenter7.0证书web续期发生错误

1. 故障描述 vSphere Client 版本 7.0.2.00200 vCenter _MACHINE_CERT快到期了&#xff0c;通过web界面更新证书失败 第一步先这样&#xff0c;重新续订一下证书 续订发生错误 2. 解决办法 2.1. 前提工作 登陆ssh到vcenter&#xff0c;重新生成证书 先关掉HA&#xff…

Oracle报错ORA-01653: 表xx无法通过 8192在表空间中扩展

向Oracle 19g数据库中批量插入数据&#xff0c;当插入近2亿条数据后&#xff0c;报出如下错误&#xff1a; ORA-01653: 表xx无法通过 8192 (在表空间 xx_data 中) 扩展 查看表空间&#xff0c;发现表空间大小已达到32G&#xff0c;表空间无法进行自动扩展了。&#xff08;初始…

数据结构(3)单链表的模拟实现

上一节我们进行了数据结构中的顺序表的模拟式现&#xff0c;今天我们来实现一下另外一个数据结构&#xff1a;单链表。 我们在实现顺序表之后一定会引发一些问题和思考&#xff1a; 1.顺序表在头部和中间插入数据会用到循环&#xff0c;时间复杂O&#xff08;N&#xff09; …

如何高效的向AI大模型提问? - 提示工程Prompt Engineering

大模型的输入&#xff0c;决定了大模型的输出&#xff0c;所以一个符合要求的提问Prompt起到关键作用。 以下是关于提示工程Prompt Engineering主要方法的详细表格&#xff0c;包括每种方法的优点、缺点、应用场景以及具体示例&#xff1a; 主要方法优点缺点应用场景示例明确性…

python正则化表示总结

1.字符 总结&#xff1a; .匹配除“\n”以外的所有字符[…]字符集&#xff0c;…为所给出的范围&#xff0c;如&#xff1a;[a-zA-Z]表示逐个列出所有字符&#xff0c;[0-9]表示逐个列出所有数字[^…]^表示取反&#xff0c;如 [^0-9] 等同于出数字以外所有字符[…]并[…]也可…