index.vue 3.8 KB

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