微信小程序列表加载更多
概述
基于小程序开发的列表加载更多例子。
详细
一、前言
基于小程序开发的列表加载更多例子。
二、运行效果
运行效果(演示的小视频,点击播放即可)
三、实现过程
总体思路如何:
1、通过scroll-view组件提供的bindscroll方法监控滚动的时候是否距离底部在40px内,如果小于40px则触发加载更多方法(见完整代码index.js里的bindscroll方法)
2、通过使用发现很多时候服务返回数据太快了,没有加载等待的过程,显的不自然,所以在loadMore方法里通过setTimeout来保证至少有333毫秒的加载时间(见完整代码index.js里的loadMore方法)
3、实际使用中又发现一个问题,上滑到底部会重复触发加载更多方法导致重复的网络请求。通过记录上次加载时间lastRequestTime,保证两次网络请求的间隔大于1秒(见完整代码index.js里的fetchList方法),这样就能避免重复调用加载更多的问题
备注:demo代码里的网络请求wx.requestTest方法是为了显示效果,所以写了个模拟的请求方法,实际使用可替换为wx.request对接自己项目的服务
具体实现如下:
1、创建小程序,点击下图里框起来的位置,创建小程序
2、在app.js里添加网络模拟方法
let serverData = [];
for(let i = 1; i < 25; i++){serverData.push({id:i, name:i})
}
App({onLaunch: function () {wx.requestTest = ({data:{page,size},success}) => {setTimeout(() => {//模拟网络返回请求let res = {data:{data:{rows: serverData.slice((page - 1) * size, size + (page - 1) * size)},result: true,}}console.log(res)success(res)},1000//模拟网络延迟)}},globalData: {}
})
3、增加和pages同层级的components文件夹,在里面创建Loading文件夹,并在下面创建以下文件
//loading.js
Component({data: {},properties: {visible: {//loading效果是否显示type: Boolean,value: false//默认不显示},},
})
//loading.json
{"component": true,//表示是组件"usingComponents": {}
}
//loading.wxss
.loadmore {width: 100%;height: 0rpx;display: flex;align-items: center;justify-content: center;padding-top:24rpx;transition: all 200ms linear;
}
.loadmore.visible {height: 80rpx;
}
.my-loading:after {content: " ";display: block;width: 26px;height: 26px;margin: 1px;border-radius: 50%;border: 2px solid #FFD800;border-color: #fff transparent #FFD800 transparent;animation: lds-dual-ring 1.2s linear infinite;
}
@keyframes lds-dual-ring {0% {transform: rotate(0deg);}100% {transform: rotate(360deg);}
}
//loading.wxml
<view class="loadmore {{visible && 'visible'}}"><view class="my-loading" wx:if="{{visible}}"></view>
</view>
4、修改pages/index文件夹下各文件如下
//index.json
{"navigationBarTitleText": "首页","usingComponents": {"loading": "/components/Loading/loading"//引用组件}
}
//index.js
const app = getApp()
let loadingMore = false
let lastScollTop = 0;
let lastRequestTime = 0;
Page({data: {list: [],hasMore: true,//列表是否有数据未加载page: 1,size: 8,//每页8条数据scrollYHeight: 0,//scroll-view高度},bindscroll: function (e) {const { scrollHeight, scrollTop } = e.detail;const { scrollYHeight, hasMore } = this.data;//如果当前没有加载中且列表还有数据未加载,且页面滚动到距离底部40px内if (!loadingMore && hasMore && (scrollHeight - scrollYHeight - scrollTop < 40) && lastScollTop <= scrollTop) {this.loadMore()}lastScollTop = scrollTop},loadMore: function () {const { page, hasMore } = this.data;if (!hasMore || loadingMore) return;loadingMore = truesetTimeout(() => {this.fetchList(page + 1, () => {loadingMore = false;})}, 333)},fetchList: function (page, cb) {let nowRequestTime = (new Date()).getTime();//限制两次网络请求间隔至少1秒if (nowRequestTime - lastRequestTime < 1000) {if (cb) cb();return;}lastRequestTime = nowRequestTime//这里wx.requestTest实际使用时换成wx.request//wx.requestTest定义见app.jswx.requestTest({url: "testUrl",header: {'Authorization': wx.getStorageSync('token')},data: {page,size: this.data.size,},success: (res) => {if (res.data && res.data.result) {let list = res.data.data.rows || [];if (list.length == 0) {this.setData({hasMore: false,page,})} else {this.setData({list: this.data.list.concat(list),hasMore: list.length == this.data.size,page,})}} else {wx.showToast({title: res.data ? res.data.message : "列表加载失败",icon: 'none',duration: 1000})}if (cb) {cb()}},fail: () => {wx.showToast({title: "列表加载失败",icon: 'none',duration: 1000})if (cb) {cb()}}})},onReady: function () {wx.getSystemInfo({success: ({ windowHeight }) => {this.setData({ scrollYHeight: windowHeight })//设置scrill-view组件的高度为屏幕高度}})},onLoad: function () {this.fetchList(1)//加载第一页数据}
})
//index.wxml
<scroll-view scroll-y style="height:{{scrollYHeight}}px" scroll-top="{{scrollTop}}" bindscroll="bindscroll"><viewclass="item"wx:for="{{list}}"wx:key="id"wx:for-index="idx">{{item.name}}</view><loading visible="{{hasMore}}"></loading>
</scroll-view>
//index.css
.item {width: 750rpx;height: 200rpx;font-size: 40rpx;color: black;position: relative;display: flex;align-items: center;justify-content: center;
}
.item::after{content: "";position: absolute;left: 0;right: 0;bottom: 0;border-bottom: 1rpx solid #eeeeee;
}
此时运行程序,可查看效果。
整体代码:
//index.js
const app = getApp()
let loadingMore = false
let lastScollTop = 0;
let lastRequestTime = 0;
Page({data: {list: [],hasMore: true,//是否有数据未加载page: 1,size: 8,scrollYHeight: 0,},bindscroll: function (e) {const { scrollHeight, scrollTop } = e.detail;const { scrollYHeight, hasMore } = this.data;//如果当前没有加载中且列表还有数据未加载,且页面滚动到距离底部40px内if (!loadingMore && hasMore && (scrollHeight - scrollYHeight - scrollTop < 40) && lastScollTop <= scrollTop) {this.loadMore()}lastScollTop = scrollTop},loadMore: function () {const { page, hasMore } = this.data;if (!hasMore || loadingMore) return;loadingMore = truesetTimeout(() => {this.fetchList(page + 1, () => {loadingMore = false;})}, 333)},fetchList: function (page, cb) {let nowRequestTime = (new Date()).getTime();if (nowRequestTime - lastRequestTime < 1000) {if (cb) cb();return;}lastRequestTime = nowRequestTime//这里wx.requestTest实际使用时换成wx.request//wx.requestTest定义见app.jswx.requestTest({url: "testUrl",header: {'Authorization': wx.getStorageSync('token')},data: {page,size: this.data.size,},success: (res) => {if (res.data && res.data.result) {let list = res.data.data.rows || [];if (list.length == 0) {if(page == 1){this.setData({hasMore: false,page,list: []})}else {this.setData({hasMore: false,page,})}} else {this.setData({list: this.data.list.concat(list),hasMore: list.length == this.data.size,page,})}} else {wx.showToast({title: res.data ? res.data.message : "列表加载失败",icon: 'none',duration: 1000})}if (cb) {cb()}},fail: () => {wx.showToast({title: "列表加载失败",icon: 'none',duration: 1000})if (cb) {cb()}}})},onReady: function () {const { windowWidth, ratio } = app.globalDatawx.getSystemInfo({success: ({ windowHeight, pixelRatio }) => {this.setData({ scrollYHeight: windowHeight })}})},onLoad: function () {this.fetchList(1)}
})//index.wxml
<scroll-view scroll-y style="height:{{scrollYHeight}}px" scroll-top="{{scrollTop}}" bindscroll="bindscroll"><viewclass="item"wx:for="{{list}}"wx:key="id"wx:for-index="idx">{{item.name}}</view><loading visible="{{hasMore}}"></loading>
</scroll-view>//index.css
.item {width: 750rpx;height: 200rpx;font-size: 40rpx;color: black;position: relative;display: flex;align-items: center;justify-content: center;
}
.item::after{content: "";position: absolute;left: 0;right: 0;bottom: 0;border-bottom: 1rpx solid #eeeeee;
}//app.js
let serverData = [];
for(let i = 1; i < 25; i++){serverData.push({id:i, name:i})
}
App({onLaunch: function () {wx.requestTest = ({data:{page,size},success}) => {setTimeout(() => {//模拟网络返回请求let res = {data:{data:{rows: serverData.slice((page - 1) * size, size + (page - 1) * size)},result: true,}}console.log(res)success(res)},1000//模拟网络延迟)}},globalData: {}
})
三、项目结构
四、其他补充
暂时没有
相关文章:

微信小程序列表加载更多
概述 基于小程序开发的列表加载更多例子。 详细 一、前言 基于小程序开发的列表加载更多例子。 二、运行效果 运行效果(演示的小视频,点击播放即可) 三、实现过程 总体思路如何: 1、通过scroll-view组件提供的bindscroll方法…...

数据库知识
怎么做 常见的数据库 Oracle Mysql SOLSever Navicat (新版可以链接mysql oracle) http://sqlfiddle.com/ 数据库操作在线练习 mysql自带四个数据库 数据库语言的使用 显示数据库:show databases; 创建数据库:…...
VUE 目录介绍
更新升级(npm - i)之后最终目录如下: total 1672 drwxr-xr-x 18 testrose staff 576 8 22 02:53 . drwxr-xr-x 24 testrose staff 768 8 22 02:50 .. -rw-r--r-- 1 testrose staff 402 8 22 02:52 .babelrc -rw…...

Selenium的基本使用
文章目录 引入一.选择元素的基本方法1.根据id 选择元素2.根据 class属性选择元素当元素有 多个class类型 时 3.根据 tag名 选择元素4.通过WebElement对象选择元素5.find_element 和 find_elements 的区别 二.等待界面元素出现1.隐式等待2.显示等待 三.操控元素的基本方法1.点击…...

数据结构-----树的易错点
1.树的度和m叉树 •度为m的树(度表示该结点有多少个孩子(分支)) 任意结点的度<m(最多m个孩子) 至少又一个结点度m(有m个孩子) 一定是非空树,至少有m1个结点 •m叉树 任意结点的度<m(最多有m个孩子) 允许所…...

写之前的项目关于使用git remote -v 找不到项目地址的解决方案
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、报错解析1. 报错内容2. 报错翻译3. 报错解析(1)使用git branch来查看git仓库有几个分支(2)使用git remote -v&am…...

STM32 F103C8T6学习笔记9:0.96寸单色OLED显示屏—自由取模显示—显示汉字与图片
今日学习0.96寸单色OLED显示屏的自由取模显示: 宋体汉字比较复杂,常用字符可以直接复制存下来,毕竟只有那么几十个字母字符,但汉字实在太多了,基本不会全部放在单片机里存着,一般用到多少个字就取几个字的模ÿ…...

直播平台源码搭建协议讲解篇:传输控制协议TCP
简介: 由于直播平台在当今时代发展的越来越迅速,使得直播平台的技术功能越来越智能,让用户在直播平台中能够和其他用户进行实时互动,让用户可以获取到全世界最新的资讯,让一些用户可以作为主播获得工作,让…...

中文编码问题:raw_input输入、文件读取、变量比较等str、unicode、utf-8转换问题
最近研究搜索引擎、知识图谱和Python爬虫比较多,中文乱码问题再次浮现于眼前。虽然市面上讲述中文编码问题的文章数不胜数,同时以前我也讲述过PHP处理数据库服务器中文乱码问题,但是此处还是准备简单做下笔记。方便以后查阅和大家学习。 …...

基于Jenkins自动打包并部署Tomcat环境
目录 1、配置git主机 2、配置jenkins主机 3、配置web主机 4、新建Maven项目 5、验证 Jenkins 自动打包部署结果 Jenkins 的工作原理是先将源代码从 SVN/Git 版本控制系统中拷贝一份到本地,然后根据设置的脚本调用Maven进行 build(构建)。…...

开利网络受邀参与御盛马术庄园发展专委会主题会议
近日,开利网络受邀参与深度合作客户御盛马术庄园组织的首届发展专委会主体会议,就马术庄园发展方向进行沟通,数字化也是重要议题之一。目前,御盛马术庄园已经完成数字化系统的初步搭建,将通过线上线下相结合的方式搭建…...

无类别域间路由(Classless Inter-Domain Routing, CIDR):理解IP网络和子网划分(传统的IP地址类ABCDE:分类网络)
文章目录 无类别域间路由(CIDR):理解IP网络和子网划分引言传统的IP地址类关于“IP地址的浪费” IP地址与CIDRIP地址概述网络号与主机号CIDR记法(网络 网络地址/子网掩码)网络和广播地址 CIDR的优势减少路由表项缓解IP…...
合宙Air724UG LuatOS-Air LVGL API-概念
概念 在 LVGL 中,用户界面的基本构建块是对象。例如,按钮,标签,图像,列表,图表或文本区域。 属性 基本属性 所有对象类型都共享一些基本属性: Position (位置) Size (尺寸) Parent (父母) Cli…...

【C语言】位段,枚举和联合体详解
目录 1.位段 1.1 什么是位段 1.2 位段的内存分配 1.3 位段的跨平台问题 2.枚举 2.1 枚举类型的定义 2.2 枚举的优点 3. 联合(共用体) 3.1 联合类型的定义 3.2 联合的特点 3.3 联合大小的计算 1.位段 1.1 什么是位段 位段的声明和结构体是类…...
python学习-文件管理
文件管理 shutil 文件拷贝 shutil.copy(src,dst) 注:srcrE:\python\.vscode\文件操作 windows上运行时候,如果不加r,上述文件路径在代码运行时会报错,因为其会先将双引号”“去掉,然后系统看到了文件路径中有\nc&…...
【LeetCode 算法】Number of Ways of Cutting a Pizza 切披萨的方案数-记忆化
文章目录 Number of Ways of Cutting a Pizza 切披萨的方案数问题描述:分析代码递归 Tag Number of Ways of Cutting a Pizza 切披萨的方案数 问题描述: 给你一个 rows x cols 大小的矩形披萨和一个整数 k ,矩形包含两种字符: A…...
机器视觉之光流
光流(Optical Flow)是计算机视觉领域的一个重要概念,用于描述图像中物体的运动模式。光流可以用来跟踪图像中物体的运动,检测运动中的物体,或者在机器视觉任务中估计物体的速度和位移。 光流的基本思想是根据图像像素…...

C++:list使用以及模拟实现
list使用以及模拟实现 list介绍list常用接口1.构造2.迭代器3.容量4.访问数据5.增删查改6.迭代器失效 list模拟实现1.迭代器的实现2.完整代码 list介绍 list是一个类模板,加<类型>实例化才是具体的类。list是可以在任意位置进行插入和删除的序列式容器。list的…...

深度学习基础知识-pytorch数据基本操作
1.深度学习基础知识 1.1 数据操作 1.1.1 数据结构 机器学习和神经网络的主要数据结构,例如 0维:叫标量,代表一个类别,如1.0 1维:代表一个特征向量。如 [1.0,2,7,3.4] 2维:就是矩…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...

听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...

Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...