0


猿创征文|Vue结合Vant-ui实现数据列表上拉加载更多,下拉刷新功能

⭐️⭐️⭐️ 作者:船长在船上
🚩🚩🚩 主页:来访地址船长在船上的博客
🔨🔨🔨 简介:CSDN前端领域优质创作者,资深前端开发工程师,专注前端开发,在CSDN总结工作中遇到的问题或者问题解决方法以及对新技术的分享,欢迎咨询交流,共同学习。

🔔🔔🔔 感谢:如果觉得博主的文章不错或者对你的工作有帮助或者解决了你的问题,可以关注、支持一下博主,如果三连收藏支持就会更好,在这里博主不胜感激!!!如有疑问可以留言、评论,看到后会及时回复。

功能需求:获取后端接口返回的数据,实现列表数据上滑加载更多下一页数据,下拉数据刷新功能,结合vant-ui框架实现。可直接参考使用。

下拉刷新效果:

上拉加载下一页效果:

知识点速记

基本用法

**List **通过

  1. loading

  1. finished

两个变量控制加载状态,当组件滚动到底部时,会触发

  1. load

事件并将

  1. loading

设置成

  1. true

。此时可以发起异步操作并更新数据,数据更新完毕后,将

  1. loading

设置成

  1. false

即可。若数据已全部加载完毕,则直接将

  1. finished

设置成

  1. true

即可。

下拉刷新

List 组件可以与PullRefresh组件结合使用,实现下拉刷新的效果。

** 注意事项:**

  • v-model : 是否处于加载状态,加载过程中不触发load事件
  • finished: 是否已加载完成,加载完成后不再触发load事件
  • offset : 滚动条与底部距离小于 offset 时触发load事件
  • loading-text 加载过程中的提示文字
  • finished-text 加载完成后的提示文字
  1. List

有以下三种状态,理解这些状态有助于你正确地使用

  1. List

组件:

  • 非加载中,loadingfalse,此时会根据列表滚动位置判断是否触发load事件(列表内容不足一屏幕时,会直接触发)
  • 加载中,loadingtrue,表示正在发送异步请求,此时不会触发load事件
  • 加载完成,finishedtrue,此时不会触发load事件

在每次请求完毕后,需要手动将

  1. loading

设置为

  1. false

,表示加载结束

事件使用:@load方法

滚动条与底部距离小于 offset 时触发

代码实现

1.页面布局

  1. <template>
  2. <div class="myOrder">
  3. <!--公共头部组件-->
  4. <nav-bar-top :titleText="titleName" :arrowTrue="arrowTrue"></nav-bar-top>
  5. <!--主体部分-->
  6. <div class="tabMain" style="margin-top:0">
  7. <div v-if="noData" class="p30 text-center fontSize30">
  8. <van-empty class="custom-image" :image="zwdd"/>
  9. </div>
  10. <van-pull-refresh v-model="isLoading" @refresh="onRefresh" class="content" success-text="刷新成功">
  11. <!-- 加载 -->
  12. <van-list v-if="contractData.length>0" v-model="loading" :finished="finished" :immediate-check="false" finished-text="我也是有底线的"
  13. @load="onLoad" :offset="10">
  14. <van-row class="m30 p30 capaIttem" v-for="item in contractData" :key="item.orderId">
  15. <van-col span="24" class="fontSize30">
  16. <div class="focus-con">
  17. <!-- ellipsis-orderNumber -->
  18. <div class="focus-title">
  19. <span class="color3 van-ellipsis">合同编号:{{item.contractNumber}}</span>
  20. <!-- <span class="color3 van-ellipsis">{{item.outsideContractId?'订单':'合同'}}编号:{{item.contractNumber}}</span> -->
  21. <!-- <img src="../../assets/index/VIPICO.png" class="vipIcon pl20"> -->
  22. </div>
  23. <!-- 发票开具状态(0:待申请,1:待审核,2:审核未通过,3:审核已通过) -->
  24. <div>
  25. <van-tag :text-color="item.status=='0'?'#FF9133':item.status=='1'?'#4972FF':item.status=='2'?'#F1403C':'#00CE80'" class="tagStyle">
  26. {{item.status=="0"?"待申请":item.status=="1"?"待审核":item.status=="2"?"审核未通过":"审核通过"}}
  27. </van-tag>
  28. </div>
  29. </div>
  30. </van-col>
  31. <van-col span="24" class="mt10">
  32. <div class="capa-box">
  33. <div class="focus-title" >
  34. <span class="color3 shipName fontSize32">{{item.userName}}</span>
  35. </div>
  36. </div>
  37. <div class="capa-box">
  38. <div class="color6 flex align-items fontSize24 van-ellipsis ellipsis-content">
  39. <img src="../../assets/img/huo.png" class="huoIcon mr5">
  40. {{item.unlimitedLoading&&item.unlimitedLoading=="1"?"随船装/":""}}
  41. <span class="" v-if="item.cargoWeight">{{item.cargoWeight}}吨/</span>
  42. <span class="van-ellipsis">{{item.cargoName?item.cargoName:""}}</span>
  43. </div>
  44. </div>
  45. </van-col>
  46. <van-col span="24" class="capa-body">
  47. <div class="capa-con fontSize28">
  48. <div class="content-left">
  49. <img src="../../assets/index/zhuang.png" alt="" class=" mr5">
  50. <span>{{item.loadingPort}}</span>
  51. </div>
  52. <img src="../../assets/index/arrows.png" class="capa-jt">
  53. <div class="content-right">
  54. <img src="../../assets/index/xie.png" alt="" class=" mr5">
  55. <span>{{item.arrivePort}}</span>
  56. </div>
  57. </div>
  58. <div class="capa-time mt10">
  59. <div class="capa-time-left">
  60. <div class="time-img">
  61. <img src="../../assets/index/time.png" class="capaImg">
  62. <span class="timeTXT fontSize28 pl10">装货时间</span>
  63. </div>
  64. <div class="timeColor fontSize34 mt10 timeError">
  65. {{item.loadingTime?item.loadingTime:"暂无"}}
  66. </div>
  67. </div>
  68. <div style="height:50px;border-left:1px solid #E1E1E1"></div>
  69. <div class="capa-time-right">
  70. <div class="time-img priceContent">
  71. <img src="../../assets/index/money.png" class="capaImg">
  72. <span class="timeTXT fontSize28 pl10">合同金额</span>
  73. </div>
  74. <div>
  75. <div class="timeColor fontSize34 mt10 floatRight">
  76. <span v-if="item.contractAmount">
  77. {{item.priceType=="0"?item.contractAmount+"元":item.priceType=="1"?item.contractAmount+"元/吨":item.contractAmount+"元"}}
  78. </span>
  79. <span v-else>暂无报价</span>
  80. </div>
  81. </div>
  82. </div>
  83. </div>
  84. </van-col>
  85. <van-col style="width:100%" class="mt20">
  86. <div class="flex flex-end">
  87. <van-button plain type="info" class="borderRaduis" size="small" @click="handleLook(item)">查看合同</van-button>
  88. <van-button v-show="item.status=='2'" plain type="info ml20" class="borderRaduis" size="small" @click="handleFail(item,item.invoiceId)">失败原因</van-button>
  89. <van-button class="ml20 borderRaduis" color="#024ee0" type="info" size="small">{{item.status=='2'?'重新申请':'申请开票'}}</van-button>
  90. </div>
  91. </van-col>
  92. </van-row>
  93. </van-list>
  94. </van-pull-refresh>
  95. </div>
  96. </div>
  97. </template>

2.样式

  1. .myOrder{
  2. height: 100vh;
  3. overflow-y: auto;
  4. }
  5. ::v-deep.van-cell {
  6. font-size: 14px;
  7. }
  8. .capaIttem {
  9. box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.06);
  10. border-radius: 24px;
  11. background: #fff;
  12. position: relative;
  13. }
  14. ::v-deep.van-cell {
  15. padding: 10px 0;
  16. }
  17. ::v-deep.van-cell {
  18. font-size: 40px;
  19. line-height: 40px;
  20. font-size: 30px;
  21. }
  22. ::v-deep.van-field__left-icon .van-icon {
  23. font-size: 30px;
  24. }
  25. ::v-deep.van-tag {
  26. font-size: 24px;
  27. line-height: 40px;
  28. }
  29. ::v-deep.van-button--small {
  30. height: 60px;
  31. font-size: 24px;
  32. }
  33. ::v-deep.van-tabs--line .van-tabs__wrap {
  34. height: 88px;
  35. }
  36. ::v-deep.van-tab {
  37. font-size: 30px;
  38. }
  39. .searchBtnFixed {
  40. position: fixed;
  41. top: 0;
  42. left: 80px;
  43. height: 92px;
  44. line-height: 92px;
  45. z-index: 1000;
  46. width: 86%;
  47. overflow: hidden;
  48. }
  49. ::v-deep.van-search {
  50. position: absolute;
  51. top: -8px;
  52. // padding: 13px;
  53. width: 100%;
  54. }
  55. ::v-deep.van-search__content {
  56. background: #eeeeee;
  57. border-radius: 16px;
  58. padding: 5px 10px;
  59. }
  60. .focusSearch ::v-deep.van-icon-clear {
  61. padding-right: 160px;
  62. }
  63. // 搜索
  64. .onSearch {
  65. position: absolute;
  66. right: 50px;
  67. top: 28px;
  68. font-size: 30px;
  69. height: 36px;
  70. line-height: 36px;
  71. border-left: 1px solid #cccccd;
  72. padding-left: 30px;
  73. color: #024ee0;
  74. }
  75. // 新增
  76. .focus-con {
  77. display: flex;
  78. justify-content: space-between;
  79. border-bottom: 1px solid #ebedf0;
  80. padding-bottom: 20px;
  81. }
  82. .capa-title {
  83. border-bottom: 1px solid #ebedf0;
  84. padding-bottom: 20px;
  85. display: flex;
  86. align-items: center;
  87. }
  88. .focus-title {
  89. display: flex;
  90. align-items: center;
  91. justify-content: space-between;
  92. font-weight: 600;
  93. }
  94. .vipIcon {
  95. width: 72px;
  96. height: 34px;
  97. }
  98. .capa-box {
  99. display: flex;
  100. justify-content: space-between;
  101. align-items: center;
  102. padding-bottom: 10px;
  103. }
  104. .capa-body {
  105. background: #f5f8ff;
  106. border-radius: 0.13333rem;
  107. padding: 0.33333rem;
  108. }
  109. .capa-con {
  110. display: flex;
  111. justify-content: space-between;
  112. align-items: center;
  113. font-weight: 600;
  114. }
  115. .content-left,
  116. .content-right {
  117. display: flex;
  118. justify-content: space-between;
  119. align-items: center;
  120. img {
  121. width: 0.5rem;
  122. height: 0.5rem;
  123. }
  124. }
  125. .capa-time {
  126. display: flex;
  127. justify-content: space-between;
  128. align-items: center;
  129. }
  130. .time-img {
  131. display: flex;
  132. align-items: center;
  133. }
  134. .capaImg {
  135. width: 30px;
  136. }
  137. .timeColor {
  138. font-weight: 700;
  139. color: #024ee0;
  140. }
  141. .order-group {
  142. display: flex;
  143. align-items: center;
  144. }
  145. .ellipsis-orderNumber{
  146. span{
  147. display: inline-block;
  148. width: 310px;
  149. }
  150. }
  151. .ellipsis-txt {
  152. display: inline-block;
  153. max-width: 200px;
  154. text-align: start;
  155. }
  156. .shipName {
  157. font-weight: 600;
  158. display: flex;
  159. align-items: center;
  160. }
  161. .orderNameWidth{
  162. max-width: 220px;
  163. }
  164. .ellipsis-content{
  165. width: 400px;
  166. }
  167. .priceContent{
  168. display: flex;
  169. justify-content: flex-end;
  170. }
  171. .floatRight{
  172. float: right;
  173. }
  174. .borderRaduis {
  175. border-radius: 10px;
  176. height: 56px;
  177. .van-button__text {
  178. font-size: 26px;
  179. }
  180. }
  181. .huoIcon{
  182. width: 26px;
  183. height: 26px;
  184. }
  185. .tagStyle{
  186. background-color: #fff !important;
  187. }
  188. .contactTel {
  189. width: 90%;
  190. border-radius: 10px;
  191. }
  192. .popup-header{
  193. height: 100px;
  194. text-align: center;
  195. color:#fff;
  196. background: #024EE0;
  197. line-height: 100px;
  198. }
  199. .contactTel ::v-deep.van-popup__close-icon--top-right{
  200. top:26px !important;
  201. color:#fff !important;
  202. }
  203. .popup-box{
  204. margin:60px 50px 30px;
  205. }
  206. .popup-btn{
  207. width: 100%;
  208. border-radius: 20px;
  209. font-size: 36px;
  210. }
  211. .popupTitle {
  212. box-sizing: border-box;
  213. padding: 35px 0 61px 0;
  214. font-size: 32px;
  215. color: #333333;
  216. font-weight: 500;
  217. }
  218. .imgContent {
  219. display: flex;
  220. align-items: center;
  221. justify-content: space-around;
  222. flex-wrap: wrap;
  223. margin-bottom: 30px;
  224. padding: 0 10px;
  225. li {
  226. width: 125px;
  227. height: 125px;
  228. margin-bottom: 37px;
  229. background-color: black;
  230. margin-right: 25px;
  231. }
  232. li:nth-of-type(4n) {
  233. margin-right: 0;
  234. }
  235. }

3.方法

data数据定义:

  1. data() {
  2. return {
  3. zwdd:require("../../assets/img/zwdd.png"),
  4. titleName: "我要开票",
  5. arrowTrue: true,
  6. page: 1,
  7. pageSize: 10,
  8. isLoading: false,
  9. loading: false,
  10. finished: false,
  11. noData: false,
  12. contractData: [],
  13. timer:null,
  14. };
  15. },

加载更多方法onLoad

  1. // 加载更多
  2. onLoad() {
  3. this.loading = true;
  4. this.timer = setTimeout(() => {
  5. this.page++;
  6. this.getInvoicingContractListFun();
  7. }, 1000);
  8. },

下拉刷新方法onRefresh:下拉刷新调用接口,并且页数=1

  1. // 刷新
  2. onRefresh() {
  3. this.isLoading = true;
  4. this.page = 1;
  5. if (this.contractData.length == 0) {
  6. this.isLoading = false;
  7. }
  8. this.getInvoicingContractListFun();
  9. },

处理数据列表方法getInvoicingContractListFun:

调用接口,传递相应的参数,获取到数据,去判断处理数据数据的加载,数据合并操作,利用定义的loading、finished、isLoading控制数据上拉数据加载。

  1. // 数据列表方法
  2. getInvoicingContractListFun() {
  3. let params = {
  4. carrierUserId: this.id,
  5. pageNum: this.page,
  6. pageSize: this.pageSize
  7. };
  8. getInvoicingContractList(params)
  9. .then(res => {
  10. if (res.code == 200) {
  11. if (this.contractData.length > 0) {
  12. this.noData = false;
  13. //当请求前有数据时 第n次请求
  14. if (this.loading) {
  15. // 上拉加载
  16. this.contractData = this.contractData.concat(res.data.records); //上拉加载新数据添加到数组中
  17. this.$nextTick(() => {
  18. //在下次 DOM 更新循环结束之后执行延迟回调
  19. this.loading = false; //关闭上拉加载中
  20. });
  21. if (res.data.records.length == 0) {
  22. //没有更多数据
  23. this.finished = true; //上拉加载完毕
  24. }
  25. }
  26. if (this.isLoading) {
  27. //关闭下拉刷新
  28. this.isLoading = false; //关闭下拉刷新中
  29. this.contractData = res.data.records; //重新给数据赋值
  30. if (this.finished) {
  31. //如果上拉加载完毕为true则设为false。解决上拉加载完毕后再下拉刷新就不会执行上拉加载问题
  32. this.finished = false;
  33. }
  34. }
  35. } else {
  36. this.noData = false;
  37. this.loading = false;
  38. this.isLoading = false;
  39. this.finished = false;
  40. //当请求没有数据时 第一次请求
  41. if (res.data.records.length == 0) {
  42. this.noData = true;
  43. } else {
  44. this.contractData = res.data.records;
  45. }
  46. }
  47. } else {
  48. this.$toast(res.msg);
  49. }
  50. })
  51. .catch(error => {});
  52. },

created中调用方法获取数据

  1. created(){
  2. //方法调用
  3. this.getInvoicingContractListFun();
  4. }

最后在beforeDestroy生命周期清除定时器

  1. beforeDestroy() {
  2. clearTimeout(this.timer);
  3. this.timer = null;
  4. }

👉👉👉 欢迎来访船长在船上的博客,文章持续更新;如有疑问可以留言、评论,看到后会及时回复。


本文转载自: https://blog.csdn.net/SmartJunTao/article/details/126558553
版权归原作者 船长在船上 所有, 如有侵权,请联系我们删除。

“猿创征文|Vue结合Vant-ui实现数据列表上拉加载更多,下拉刷新功能”的评论:

还没有评论