当前位置: 首页 > news >正文

scroll-view分页加载

一、核心原理

分页加载的核心逻辑是:当scroll-view滚动到底部时,触发数据请求,获取下一页数据并追加到现有列表中。关键需实现两个核心点:

  • 准确监听scroll-view的滚动到底部事件

  • 管理分页状态(当前页码、是否加载中、是否已无更多数据),避免重复请求或无效请求

二、基础配置(scroll-view属性)

需为scroll-view设置以下关键属性,确保滚动监听正常:

lower-threshold

Number

距底部/右边多远时(单位px)触发scrolltolower事件,默认50px

scrolltolower

EventHandle

滚动到底部/右边时触发的事件(核心事件)

style="height: 具体高度"

String

必须给scroll-view设置固定高度,否则无法正常滚动和触发事件

三、完整代码实现

以下是可直接复用的完整示例,包含页面结构、样式、逻辑(以获取列表数据为例):

3.1 页面结构(template)

<template> <view class="container"> <!-- 分页列表容器:scroll-view --> <scroll-view class="scroll-list" scroll-y scroll-with-animation lower-threshold="100" @scrolltolower="loadMoreData" > <!-- 列表项 --> <view class="list-item" v-for="(item, index) in listData" :key="index"> {{ item.title }} </view> <!-- 加载状态提示 --> <view class="load-status"> {{ loadStatusText }} </view> </scroll-view> </view> </template>

3.2 样式(style)

<style scoped> .container { width: 100%; height: 100vh; /* 占满整个视口高度 */ } /* 关键:scroll-view必须设置固定高度 */ .scroll-list { width: 100%; height: 100%; padding: 10rpx; box-sizing: border-box; } .list-item { width: 100%; height: 200rpx; line-height: 200rpx; text-align: center; border: 1rpx solid #eee; border-radius: 10rpx; margin-bottom: 10rpx; } .load-status { text-align: center; padding: 20rpx 0; color: #999; font-size: 24rpx; } </style>

3.3 逻辑(script)

<script> export default { data() { return { listData: [], // 列表数据 pageNum: 1, // 当前页码(默认从1开始) pageSize: 10, // 每页条数 isLoading: false, // 是否正在加载中(防止重复请求) hasMore: true, // 是否还有更多数据 loadStatusText: "下拉加载更多" // 加载状态提示文本 }; }, onLoad() { // 页面加载时,初始化第一页数据 this.initData(); }, methods: { // 初始化第一页数据 async initData() { this.pageNum = 1; // 重置页码 this.listData = []; // 清空列表 this.hasMore = true; // 重置是否有更多数据 await this.getListData(); // 请求数据 }, // 核心:请求列表数据 async getListData() { // 防止重复请求 if (this.isLoading) return; // 标记为加载中 this.isLoading = true; this.loadStatusText = "加载中..."; try { // 1. 发起请求(替换为你的真实接口地址) const res = await uni.request({ url: "https://api.example.com/list", // 示例接口 method: "GET", data: { pageNum: this.pageNum, pageSize: this.pageSize } }); // 2. 处理接口返回数据(根据实际接口格式调整) const { code, data, msg } = res.data; if (code === 200) { const currentPageData = data.list; // 当前页数据 const total = data.total; // 总数据条数 // 3. 追加数据(第一页直接赋值,后续页追加) if (this.pageNum === 1) { this.listData = currentPageData; } else { this.listData = [...this.listData, ...currentPageData]; } // 4. 判断是否还有更多数据(当前累计条数 >= 总条数,则无更多) if (this.listData.length >= total) { this.hasMore = false; this.loadStatusText = "已加载全部数据"; } else { this.loadStatusText = "下拉加载更多"; } } else { uni.showToast({ title: msg || "请求失败", icon: "none" }); } } catch (error) { console.error("列表数据请求失败:", error); uni.showToast({ title: "网络异常", icon: "none" }); } finally { // 无论成功失败,都标记为加载完成 this.isLoading = false; } }, // 滚动到底部触发:加载下一页 loadMoreData() { // 若没有更多数据或正在加载中,不触发请求 if (!this.hasMore || this.isLoading) return; // 页码+1,请求下一页 this.pageNum++; this.getListData(); } } }; </script>

四、关键注意事项

1. scroll-view必须设置固定高度:这是最容易踩坑的点!如果不设置固定高度,scroll-view会被内容撑开,无法触发滚动事件。可通过父容器定高、scroll-view设置height: 100%继承,或直接设置height: xxxpx实现。

2. 防止重复请求:通过isLoading状态控制,请求发起时设为true,请求完成(无论成功失败)设为false,避免滚动到底部时多次触发请求。

3. 处理无更多数据场景:通过hasMore状态和总条数判断,当已加载数据等于总条数时,设置hasMore为false,不再触发后续请求,并更新提示文本。

4. lower-threshold合理设置:默认50px,可根据需求调整。值太小可能导致用户快速滚动时漏触发,值太大可能提前触发加载。

5. 下拉刷新扩展:如果需要下拉刷新功能,可在scroll-view上添加@scrolltoupper事件(滚动到顶部),结合下拉刷新动画实现,逻辑与分页加载类似(重置页码,重新请求第一页)。

6. 数据缓存与重置:如果页面有筛选、搜索等功能,触发筛选后需调用initData方法,重置页码、清空列表,重新加载第一页数据。

五、常见问题排查

5.1 滚动到底部不触发scrolltolower事件?

  • 检查scroll-view是否设置了固定高度

  • 检查scroll-y是否设为true(纵向滚动必须开启)

  • 检查内容是否足够长(内容高度需超过scroll-view高度才能滚动)

5.2 多次触发加载请求?

  • 确保isLoading状态控制有效,请求发起时设为true,完成后设为false

  • 适当增大lower-threshold值,避免快速滚动时连续触发

5.3 数据加载后页面不滚动?

检查是否在数据更新后触发了不必要的DOM重绘,或scroll-view的高度设置被动态改变。可通过uni.createSelectorQuery()获取scroll-view高度,确认是否正常。

http://www.jsqmd.com/news/149791/

相关文章:

  • python建筑工程项目管理系统设计与实现_95ig3zyt
  • ClearML自动化TensorFlow超参搜索流程
  • python教学管理自动化系统设计与实现 大学课程课表管理系统_54r67p9b
  • 知识蒸馏实战:Teacher-Student模型训练流程
  • 篮球计时器FPGA设计:Verilog语言实现
  • 数据迁移与ETL流程的测试验证框架
  • ms08-067漏洞复现:漏洞原理+环境搭建+渗透实战(CVE-2008-4250) - 详解
  • 探索C#运控框架:基于雷赛DMC系列的运动控制项目
  • Huggingface 214页训练手册:揭露构建世界级大模型的秘密
  • 梯度裁剪(Gradient Clipping)策略选择指南
  • 针刺热失控硬壳三元镍钴锰酸锂电池NCM系列的Comsol模拟计算探索
  • 探索基于模型预测算法的含储能微网双层能量管理模型
  • 学长亲荐8个AI论文软件,助你搞定本科生毕业论文!
  • 傅里叶变换(二):旋转楼梯
  • 探索蒙泰卡罗模拟与水晶球:从理论到实践
  • 实用指南:【OpenCV】Python图像处理之图像预处理
  • 自监督学习SimCLR:TensorFlow 2.x复现
  • A/B测试与功能开关的流程集成与管理规范
  • PHP CORS 携带 Cookie 详解:为什么你一登录就跨域失败?
  • 融合自适应惯性权重和柯西变异的秃鹰搜索算法(Matlab实现)
  • [USACO 1.5.4]跳棋的挑战题解
  • 实用指南:《Linux系统编程之进程环境》【地址空间】
  • Flax/JAX能否取代TensorFlow?深度对比分析
  • 探索纯金属枝晶凝固模型之多点枝晶相场模型cmsol源码
  • 探索AEB距离模型:从理论到Simulink仿真
  • 多团队并行开发下的测试协调与集成策略
  • Theano遗产继承者:TensorFlow的历史使命
  • 三菱Q06UDV PLC在锂电池组盘机中的应用实践
  • Adafactor内存优化:超大模型训练必备
  • 合规性驱动的测试流程:构筑医疗金融行业的数字信任基石