index.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <template>
  2. <view class="lsv-container">
  3. <mescroll-uni
  4. ref="mescrollRef"
  5. :fixed="false"
  6. :up="upOption"
  7. :down="downOption"
  8. @up="upCallback"
  9. @down="downCallback"
  10. @init="mescrollInit"
  11. @scroll="onScroll">
  12. <view class="lsv-list">
  13. <slot name="list" :data="dataList" :is-scrolling="isScrolling"></slot>
  14. <!-- 始终显示的底部提示 -->
  15. <view class="lsv-footer">
  16. {{ hasMoreData ? '上拉加载更多' : '-- 暂无更多数据 --' }}
  17. </view>
  18. </view>
  19. </mescroll-uni>
  20. </view>
  21. </template>
  22. <script>
  23. export default {
  24. name: '',
  25. props: {
  26. // 数据接口
  27. api: {
  28. type: Object,
  29. required: true,
  30. default: null
  31. },
  32. // 初始参数
  33. init: {
  34. type: Object,
  35. default: () => ({})
  36. },
  37. emptyText: {
  38. type: String,
  39. default: ''
  40. },
  41. emptyBtnText: {
  42. type: String,
  43. default: ''
  44. },
  45. // 自定义list数据的字段
  46. keyName: {
  47. type: String,
  48. default: 'records'
  49. },
  50. // page相关
  51. noPage: {
  52. type: Boolean,
  53. default: false
  54. },
  55. pageSize: {
  56. type: [Number, String],
  57. default: 10
  58. },
  59. },
  60. data() {
  61. return {
  62. params: {},
  63. dataList: [],
  64. // 是否有更多数据
  65. hasMoreData: true,
  66. // 下拉刷新的配置
  67. downOption: {
  68. },
  69. // 是否滚动
  70. isScrolling: false,
  71. scrollTimer: null
  72. };
  73. },
  74. computed: {
  75. // 上拉加载的配置
  76. upOption() {
  77. let obj = {
  78. // noMoreSize: 5, // 如果列表已无数据,可设置列表的总数量要大于5条才显示无更多数据;
  79. onScroll: true,
  80. textLoading: '上拉加载更多...',
  81. textNoMore: '-- 暂无更多数据 --',
  82. page: {
  83. size: this.pageSize // 每页数据的数量,默认10
  84. },
  85. empty: {
  86. use: true,
  87. tip: this.emptyText || '暂无数据',
  88. btnText: this.emptyBtnText,
  89. // icon: '/static/common/empty.png',
  90. }
  91. };
  92. return obj;
  93. }
  94. },
  95. methods: {
  96. // scroll
  97. mescrollInit(e) {
  98. this.mescroll = e;
  99. },
  100. onScroll(e) {
  101. this.isScrolling = true;
  102. // 使用防抖判断滚动结束
  103. clearTimeout(this.scrollTimer);
  104. this.scrollTimer = setTimeout(() => {
  105. this.isScrolling = false;
  106. }, 200);
  107. },
  108. // 下拉刷新
  109. downCallback() {
  110. this.hasMoreData = true; // 下拉刷新时重置为有更多数据
  111. this.mescroll.resetUpScroll();
  112. },
  113. // 上拉加载
  114. upCallback(e) {
  115. if (!this.api) {
  116. this.mescroll.endErr();
  117. return;
  118. }
  119. let options = {}, params = {
  120. pageNo: e.num,
  121. pageSize: e.size,
  122. ...this.init,
  123. ...this.params
  124. };
  125. // request底层问题
  126. if (this.api.method === 'POST') {
  127. options.data = params;
  128. } else if (this.api.method === 'GET') {
  129. options.params = params;
  130. }
  131. // 置空
  132. if(e.num == 1) this.dataList = [];
  133. // 请求
  134. this.$http.request({
  135. ...this.api,
  136. ...options
  137. }).then(res => {
  138. if (res.data.code === 200) {
  139. let r = res.data.result;
  140. // 无分页处理,用于那些需要下拉和空列表的地方
  141. if (this.noPage) {
  142. r = {
  143. records: r,
  144. total: r.length
  145. };
  146. }
  147. let result = r || {}, records = r[this.keyName] || [];
  148. this.$emit('afterFetch', result);
  149. // 数据
  150. this.dataList = this.dataList.concat(records);
  151. // 判断是否还有更多数据
  152. this.hasMoreData = this.dataList.length < (result.total || result[this.keyName].total);
  153. this.mescroll.endBySize(records.length, result.total || result[this.keyName].total);
  154. } else {
  155. this.$tip.error('数据请求发生错误');
  156. this.mescroll.endErr();
  157. }
  158. }).catch(e => {
  159. this.mescroll.endErr();
  160. });
  161. },
  162. reloadList(p) {
  163. this.params = p;
  164. this.hasMoreData = true; // 重新加载时重置为有更多数据
  165. this.mescroll.resetUpScroll();
  166. }
  167. }
  168. }
  169. </script>
  170. <style lang="scss" scoped>
  171. .lsv-container {
  172. height: 100%;
  173. position: relative;
  174. .lsv-list {
  175. min-height: 100%;
  176. .lsv-footer {
  177. text-align: center;
  178. padding: 20rpx 0;
  179. font-size: 26rpx;
  180. color: #999;
  181. border-top: 1rpx solid #f7f8fc;
  182. }
  183. }
  184. }
  185. </style>