当前位置:   article > 正文

微信小程序列表加载更多_小程序加载更多数据实例

小程序加载更多数据实例

概述

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

详细

一、前言

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

二、运行效果

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

三、实现过程

总体思路如何:

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里添加网络模拟方法

  1. let serverData = [];
  2. for(let i = 1; i < 25; i++){
  3. serverData.push({id:i, name:i})
  4. }
  5. App({
  6. onLaunch: function () {
  7. wx.requestTest = ({data:{page,size},success}) => {
  8. setTimeout(
  9. () => {
  10. //模拟网络返回请求
  11. let res = {
  12. data:{
  13. data:{
  14. rows: serverData.slice((page - 1) * size, size + (page - 1) * size)
  15. },
  16. result: true,
  17. }
  18. }
  19. console.log(res)
  20. success(res)
  21. },1000//模拟网络延迟
  22. )
  23. }
  24. },
  25. globalData: {
  26. }
  27. })

3、增加和pages同层级的components文件夹,在里面创建Loading文件夹,并在下面创建以下文件

  1. //loading.js
  2. Component({
  3. data: {
  4. },
  5. properties: {
  6. visible: {//loading效果是否显示
  7. type: Boolean,
  8. value: false//默认不显示
  9. },
  10. },
  11. })
  12. //loading.json
  13. {
  14. "component": true,//表示是组件
  15. "usingComponents": {}
  16. }
  17. //loading.wxss
  18. .loadmore {
  19. width: 100%;
  20. height: 0rpx;
  21. display: flex;
  22. align-items: center;
  23. justify-content: center;
  24. padding-top:24rpx;
  25. transition: all 200ms linear;
  26. }
  27. .loadmore.visible {
  28. height: 80rpx;
  29. }
  30. .my-loading:after {
  31. content: " ";
  32. display: block;
  33. width: 26px;
  34. height: 26px;
  35. margin: 1px;
  36. border-radius: 50%;
  37. border: 2px solid #FFD800;
  38. border-color: #fff transparent #FFD800 transparent;
  39. animation: lds-dual-ring 1.2s linear infinite;
  40. }
  41. @keyframes lds-dual-ring {
  42. 0% {
  43. transform: rotate(0deg);
  44. }
  45. 100% {
  46. transform: rotate(360deg);
  47. }
  48. }
  49. //loading.wxml
  50. <view class="loadmore {{visible && 'visible'}}">
  51. <view class="my-loading" wx:if="{{visible}}"></view>
  52. </view>

4、修改pages/index文件夹下各文件如下

  1. //index.json
  2. {
  3. "navigationBarTitleText": "首页",
  4. "usingComponents": {
  5. "loading": "/components/Loading/loading"//引用组件
  6. }
  7. }
  8. //index.js
  9. const app = getApp()
  10. let loadingMore = false
  11. let lastScollTop = 0;
  12. let lastRequestTime = 0;
  13. Page({
  14. data: {
  15. list: [],
  16. hasMore: true,//列表是否有数据未加载
  17. page: 1,
  18. size: 8,//每页8条数据
  19. scrollYHeight: 0,//scroll-view高度
  20. },
  21. bindscroll: function (e) {
  22. const { scrollHeight, scrollTop } = e.detail;
  23. const { scrollYHeight, hasMore } = this.data;
  24. //如果当前没有加载中且列表还有数据未加载,且页面滚动到距离底部40px内
  25. if (!loadingMore && hasMore && (scrollHeight - scrollYHeight - scrollTop < 40) && lastScollTop <= scrollTop) {
  26. this.loadMore()
  27. }
  28. lastScollTop = scrollTop
  29. },
  30. loadMore: function () {
  31. const { page, hasMore } = this.data;
  32. if (!hasMore || loadingMore) return;
  33. loadingMore = true
  34. setTimeout(
  35. () => {
  36. this.fetchList(page + 1, () => {
  37. loadingMore = false;
  38. })
  39. }, 333
  40. )
  41. },
  42. fetchList: function (page, cb) {
  43. let nowRequestTime = (new Date()).getTime();
  44. //限制两次网络请求间隔至少1
  45. if (nowRequestTime - lastRequestTime < 1000) {
  46. if (cb) cb();
  47. return;
  48. }
  49. lastRequestTime = nowRequestTime
  50. //这里wx.requestTest实际使用时换成wx.request
  51. //wx.requestTest定义见app.js
  52. wx.requestTest({
  53. url: "testUrl",
  54. header: {
  55. 'Authorization': wx.getStorageSync('token')
  56. },
  57. data: {
  58. page,
  59. size: this.data.size,
  60. },
  61. success: (res) => {
  62. if (res.data && res.data.result) {
  63. let list = res.data.data.rows || [];
  64. if (list.length == 0) {
  65. this.setData({
  66. hasMore: false,
  67. page,
  68. })
  69. } else {
  70. this.setData({
  71. list: this.data.list.concat(list),
  72. hasMore: list.length == this.data.size,
  73. page,
  74. })
  75. }
  76. } else {
  77. wx.showToast({
  78. title: res.data ? res.data.message : "列表加载失败",
  79. icon: 'none',
  80. duration: 1000
  81. })
  82. }
  83. if (cb) {
  84. cb()
  85. }
  86. },
  87. fail: () => {
  88. wx.showToast({
  89. title: "列表加载失败",
  90. icon: 'none',
  91. duration: 1000
  92. })
  93. if (cb) {
  94. cb()
  95. }
  96. }
  97. })
  98. },
  99. onReady: function () {
  100. wx.getSystemInfo({
  101. success: ({ windowHeight }) => {
  102. this.setData({ scrollYHeight: windowHeight })//设置scrill-view组件的高度为屏幕高度
  103. }
  104. })
  105. },
  106. onLoad: function () {
  107. this.fetchList(1)//加载第一页数据
  108. }
  109. })
  110. //index.wxml
  111. <scroll-view scroll-y style="height:{{scrollYHeight}}px" scroll-top="{{scrollTop}}" bindscroll="bindscroll">
  112. <view
  113. class="item"
  114. wx:for="{{list}}"
  115. wx:key="id"
  116. wx:for-index="idx"
  117. >
  118. {{item.name}}
  119. </view>
  120. <loading visible="{{hasMore}}"></loading>
  121. </scroll-view>
  122. //index.css
  123. .item {
  124. width: 750rpx;
  125. height: 200rpx;
  126. font-size: 40rpx;
  127. color: black;
  128. position: relative;
  129. display: flex;
  130. align-items: center;
  131. justify-content: center;
  132. }
  133. .item::after{
  134. content: "";
  135. position: absolute;
  136. left: 0;
  137. right: 0;
  138. bottom: 0;
  139. border-bottom: 1rpx solid #eeeeee;
  140. }

此时运行程序,可查看效果。
 

整体代码:

  1. //index.js
  2. const app = getApp()
  3. let loadingMore = false
  4. let lastScollTop = 0;
  5. let lastRequestTime = 0;
  6. Page({
  7. data: {
  8. list: [],
  9. hasMore: true,//是否有数据未加载
  10. page: 1,
  11. size: 8,
  12. scrollYHeight: 0,
  13. },
  14. bindscroll: function (e) {
  15. const { scrollHeight, scrollTop } = e.detail;
  16. const { scrollYHeight, hasMore } = this.data;
  17. //如果当前没有加载中且列表还有数据未加载,且页面滚动到距离底部40px内
  18. if (!loadingMore && hasMore && (scrollHeight - scrollYHeight - scrollTop < 40) && lastScollTop <= scrollTop) {
  19. this.loadMore()
  20. }
  21. lastScollTop = scrollTop
  22. },
  23. loadMore: function () {
  24. const { page, hasMore } = this.data;
  25. if (!hasMore || loadingMore) return;
  26. loadingMore = true
  27. setTimeout(
  28. () => {
  29. this.fetchList(page + 1, () => {
  30. loadingMore = false;
  31. })
  32. }, 333
  33. )
  34. },
  35. fetchList: function (page, cb) {
  36. let nowRequestTime = (new Date()).getTime();
  37. if (nowRequestTime - lastRequestTime < 1000) {
  38. if (cb) cb();
  39. return;
  40. }
  41. lastRequestTime = nowRequestTime
  42. //这里wx.requestTest实际使用时换成wx.request
  43. //wx.requestTest定义见app.js
  44. wx.requestTest({
  45. url: "testUrl",
  46. header: {
  47. 'Authorization': wx.getStorageSync('token')
  48. },
  49. data: {
  50. page,
  51. size: this.data.size,
  52. },
  53. success: (res) => {
  54. if (res.data && res.data.result) {
  55. let list = res.data.data.rows || [];
  56. if (list.length == 0) {
  57. if(page == 1){
  58. this.setData({
  59. hasMore: false,
  60. page,
  61. list: []
  62. })
  63. }else {
  64. this.setData({
  65. hasMore: false,
  66. page,
  67. })
  68. }
  69. } else {
  70. this.setData({
  71. list: this.data.list.concat(list),
  72. hasMore: list.length == this.data.size,
  73. page,
  74. })
  75. }
  76. } else {
  77. wx.showToast({
  78. title: res.data ? res.data.message : "列表加载失败",
  79. icon: 'none',
  80. duration: 1000
  81. })
  82. }
  83. if (cb) {
  84. cb()
  85. }
  86. },
  87. fail: () => {
  88. wx.showToast({
  89. title: "列表加载失败",
  90. icon: 'none',
  91. duration: 1000
  92. })
  93. if (cb) {
  94. cb()
  95. }
  96. }
  97. })
  98. },
  99. onReady: function () {
  100. const { windowWidth, ratio } = app.globalData
  101. wx.getSystemInfo({
  102. success: ({ windowHeight, pixelRatio }) => {
  103. this.setData({ scrollYHeight: windowHeight })
  104. }
  105. })
  106. },
  107. onLoad: function () {
  108. this.fetchList(1)
  109. }
  110. })
  111. //index.wxml
  112. <scroll-view scroll-y style="height:{{scrollYHeight}}px" scroll-top="{{scrollTop}}" bindscroll="bindscroll">
  113. <view
  114. class="item"
  115. wx:for="{{list}}"
  116. wx:key="id"
  117. wx:for-index="idx"
  118. >
  119. {{item.name}}
  120. </view>
  121. <loading visible="{{hasMore}}"></loading>
  122. </scroll-view>
  123. //index.css
  124. .item {
  125. width: 750rpx;
  126. height: 200rpx;
  127. font-size: 40rpx;
  128. color: black;
  129. position: relative;
  130. display: flex;
  131. align-items: center;
  132. justify-content: center;
  133. }
  134. .item::after{
  135. content: "";
  136. position: absolute;
  137. left: 0;
  138. right: 0;
  139. bottom: 0;
  140. border-bottom: 1rpx solid #eeeeee;
  141. }
  142. //app.js
  143. let serverData = [];
  144. for(let i = 1; i < 25; i++){
  145. serverData.push({id:i, name:i})
  146. }
  147. App({
  148. onLaunch: function () {
  149. wx.requestTest = ({data:{page,size},success}) => {
  150. setTimeout(
  151. () => {
  152. //模拟网络返回请求
  153. let res = {
  154. data:{
  155. data:{
  156. rows: serverData.slice((page - 1) * size, size + (page - 1) * size)
  157. },
  158. result: true,
  159. }
  160. }
  161. console.log(res)
  162. success(res)
  163. },1000//模拟网络延迟
  164. )
  165. }
  166. },
  167. globalData: {
  168. }
  169. })
三、项目结构

WX20180719-134632@2x.png



  •  

四、其他补充

暂时没有

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/789405
推荐阅读
相关标签
  

闽ICP备14008679号