微信小程序列表加载更多

概述

基于小程序开发的列表加载更多例子。

详细

一、前言

基于小程序开发的列表加载更多例子。

二、运行效果

运行效果(演示的小视频,点击播放即可)

三、实现过程

总体思路如何:

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、创建小程序,点击下图里框起来的位置,创建小程序

image.png

image.png

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 = true
    setTimeout(
      () => {
        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.js
    wx.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">
    <view
      class="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 = true
    setTimeout(
      () => {
        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.js
    wx.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.globalData
    wx.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">
    <view
      class="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: {
  }
})

三、项目结构

WX20180719-134632@2x.png



  •  

四、其他补充

暂时没有

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023 网络建设与运维 X86架构计算机操作系统安装与管理题解

任务描述: 随着信息技术的快速发展,集团计划2023年把部分业务由原有的X86架构服务器上迁移到ARM架构服务器上,同时根据目前的部分业务需求进行了部分调整和优化。 一、X86架构计算机操作系统安装与管理 1.PC1系统为ubuntu-desktop-amd64系统(已安装,语言为英文),登录用户…

Golang Gorm 更新字段 save update updates

更新和删除操作的前提条件都是要在找到数据的情况下&#xff0c;先要查询到数据才可以做操作。 更新的前提的先查询到记录&#xff0c;Save保存所有字段&#xff0c;用于单个记录的全字段更新它会保控所有字段&#xff0c;即使零值也会保存。 在更新和删除之前&#xff0c;要利…

记录:ubuntu20.04+ORB_SLAM2_with_pointcloud_map+ROS noetic

由于相机实时在线运行需要ROS&#xff0c;但Ubuntu22.04只支持ROS2&#xff0c;于是重装Ubuntu20.04。上一篇文章跑通的是官方版本的ORB_SLAM2&#xff0c;不支持点云显示。高翔修改版本支持RGB-D相机的点云显示功能。 高翔修改版本ORB_SLAM2&#xff1a;https://github.com/ga…

天翼物联、汕头电信与汕头大学共建新一代信息技术与数字创新(物联网)联合实验室

近日&#xff0c;在工业和信息化部和广东省人民政府共同主办的2023中国数字经济创新发展大会上&#xff0c;天翼物联、汕头电信与汕头大学共建“新一代信息技术与数字创新&#xff08;物联网&#xff09;”联合实验室签约仪式举行。汕头大学校长郝志峰、中国电信广东公司总经理…

视频云存储/安防监控EasyCVR视频汇聚平台分发rtsp流时,出现“用户已过期”提示该如何解决?

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。音视频流媒体视频平台EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、…

主程技术分享: 游戏项目帧同步,状态同步如何选

网络游戏开发项目中帧同步,状态同步如何选&#xff1f; 网络游戏的核心技术之一就是玩家的网络同步,主流的网络同步有”帧同步”与”状态同步”。今天我们来分析一下这两种同步模式。同时教大家如何在自己的项目中采用最合适的同步方式。接下来从以下3个方面来阐述: 对啦&…

PCI9054入门1:硬件引脚定义、时序、FPGA端驱动源码

文章目录 1&#xff1a;PCI9054的FPGA侧&#xff08;local侧引脚定义&#xff09;2&#xff1a;PCI9054的C模式下的读写时序3&#xff1a;FPGA代码部分具体代码&#xff1a; 1&#xff1a;PCI9054的FPGA侧&#xff08;local侧引脚定义&#xff09; 而PCI9054的本地总线端的主要…

全国城市内涝排涝模拟技术及在市政、规划设计中应用教程

详情点击链接&#xff1a;全国城市内涝排涝模拟技术及在市政、规划设计中应用教程 一&#xff0c;数据准备 通过标准化的步骤&#xff0c;利用CAD数据、GIS数据&#xff0c;在建模的不同阶段发挥不同软件的优势&#xff0c;实现高效的数据处理、准确的参数赋值、模型的快速建…

【TA 挖坑03】雾效 | 透光材质 | Impostor | 厚度转球谐

仍旧是记录下半年想要做的东西&#xff0c;很有趣&#xff0c;实现“一团雾效” “面片也有立体感” 等等效果的一些技术上的方法。 仅粗浅记录&#xff0c;保证之后自己填坑的时候看得懂就行&#xff01; 透光 -> 透光材质ShadingModel 《永劫无间》透光材质的渲染&…

matlab面向对象

一、面向对象编程 1.1 面向过程与面向对象 区别&#xff1a; 面向过程的核心是一系列函数&#xff0c;执行过程是依次使用每个函数面向对象的核心是对象&#xff08;类&#xff09;及其属性、方法&#xff0c;每个对象根据需求执行自己的方法以解决问题 对象&#xff1a;单个…

nginx代理webSocket链接,webSocket频繁断开重连

一、场景 1、使用nginx代理webSocket链接&#xff0c;消息发送和接收都是正常的&#xff0c;但webSocket链接会频繁断开重连 2、如果不使用nginx代理则一切正常 3、程序没有做webSocket心跳处理 如下图 二、nginx代理配置 upstream cloud_ass {#ip_hash;server 192.168.1.…

MyBatis的核心技术掌握,简单易懂

目录 一.MyBatis中的动态SQL 二.MyBatis中的模糊查询 1. # 符号 2. $ 符号 ---问题 ---所以大家知道 # 和 $ 在MyBatis中的模糊查询中的区别了嘛&#xff1f;&#xff1f; 三.MyBatis 中的结果映射 1. resultType&#xff1a; 2. resultMap&#xff1a; ---问题 ---…

蓝奥声智能工业安全用电监测与智慧能源解决方案

能源管理变得越来越重要。如今&#xff0c;能源成本已成为国内预算的核心因素&#xff0c;因此用电监控对大多数现代企业来说都很重要。许多企业在日常能源消耗监控中面临着一些挑战&#xff0c;因为它们的规模庞大&#xff0c;基础设施多样化&#xff0c;灵活性低&#xff0c;…

k8s ingress (二)

k8s ingress (二) Ingress介绍 在前面课程中已经提到&#xff0c;Service对集群之外暴露服务的主要方式有两种&#xff1a;NodePort和LoadBalancer&#xff0c;但是这两种方式&#xff0c;都有一定的缺点&#xff1a; NodePort方式的缺点是会占用很多集群机器的端口&#xff0…

无涯教程-TensorFlow - XOR实现

在本章中&#xff0c;无涯教程将学习使用TensorFlow的XOR实现&#xff0c;在TensorFlow中开始XOR实施之前&#xff0c;看一下XOR表值。这将帮助了解加密和解密过程。 A B A XOR B 0 0 0 0 1 1 1 0 1 1 1 0 XOR密码加密方法基本上用于加密&#xff0c;即通过生成与适当密钥匹配…

视频汇聚平台EasyCVR安防视频监控平台新增经纬度选取功能的详细介绍

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。音视频流媒体视频平台EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、…

二、SQL注入之联合查询

文章目录 1、SQL注入原理2、SQL注入的原因3、SQL注入的危害4、SQL注入基础4.1 MySQL相关4.2 SQL注入流程&#xff1a; 5、联合注入实例基本步骤6、总结 1、SQL注入原理 SQL注入(Sql Injection&#xff09;就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串&…

【深度学习-图像识别】使用fastai对Caltech101数据集进行图像多分类(50行以内的代码就可达到很高准确率)

文章目录 前言fastai介绍数据集介绍 一、环境准备二、数据集处理1.数据目录结构2.导入依赖项2.读入数据3.模型构建3.1 寻找合适的学习率3.2 模型调优 4.模型保存与应用 总结人工智能-图像识别 系列文章目录 前言 fastai介绍 fastai 是一个深度学习库&#xff0c;它为从业人员…

项目解决问题

红外 没接收到红外信号时&#xff0c; 会有杂波干扰 STC单片机 STC的串口要用一个定时器作为波特率发生器 开定时器2需要 开定时器0 1 要ET0 1 ET11打开 串口有时候和定时器有冲突 串口发送函数放定时器中断函数中&#xff0c;时间太少可能会导致一直卡在定时器中AUXR | 0x…

计算机视觉:比SAM快50倍的分割一切视觉模型FastSAM

目录 引言 1 FastSAM介绍 1.1 FastSAM诞生 1.2 模型算法 1.3 实验结果 2 FastSAM运行环境构建 2.1 conda环境构建 2.2 运行环境安装 2.3 模型下载 3 FastSAM运行 3.1 命令行运行 3.1.1 Everything mode 3.1.2 Text prompt 3.1.3 Box prompt (xywh) 3.1.4 Points p…