ScrollRefresh.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <template>
  2. <div class="container" :style="{ height: height, overflowY: 'auto' }" @scroll.passive="getScroll($event)">
  3. <van-pull-refresh v-model="refreshLoading" @refresh="onRefresh">
  4. <slot v-bind:list="list"></slot>
  5. <template v-if="!refreshLoading && list.length > 0">
  6. <div class="bottom_text" style="margin: 20px;" v-if="loading">
  7. 加载中...
  8. </div>
  9. <div class="bottom_text" style="margin: 20px;" v-else-if="noData">
  10. 已经到底啦...
  11. </div>
  12. </template>
  13. <template v-if="list.length === 0">
  14. <div class="bottom_text" style="margin-top: 40px;">数据为空!</div>
  15. </template>
  16. </van-pull-refresh>
  17. </div>
  18. </template>
  19. <script>
  20. export default {
  21. name: 'ScrollRefresh',
  22. props: {
  23. height: {
  24. required: true,
  25. },
  26. params: {
  27. required: false,
  28. type: Object,
  29. default: function () {
  30. return {}
  31. }
  32. },
  33. request: {
  34. required: true,
  35. type: Function,
  36. },
  37. defaultLimit: {
  38. required: false,
  39. type: Number,
  40. default: function () {
  41. return 6
  42. }
  43. },
  44. },
  45. data(aaa) {
  46. return {
  47. noData: false,
  48. loading: false,
  49. refreshLoading: false,
  50. pagination: {
  51. page: 1,
  52. limit: this.defaultLimit
  53. },
  54. list: []
  55. };
  56. },
  57. mounted() {
  58. this.loadData()
  59. },
  60. methods: {
  61. // 刷新
  62. async onRefresh() {
  63. this.pagination.page = 1;
  64. this.refreshLoading = true;
  65. await this.loadData(true)
  66. this.refreshLoading = false
  67. },
  68. getScroll(event) {
  69. let scrollBottom =
  70. event.target.scrollHeight -
  71. event.target.scrollTop -
  72. event.target.clientHeight;
  73. // 距离底部20px以内 && 还有数据 && 没有正在加载中
  74. if (scrollBottom <= 20 && !this.noData && !this.loading) {
  75. this.pagination.page += 1;
  76. this.loadData()
  77. }
  78. },
  79. async loadData(isClear) {
  80. this.loading = true
  81. let parmas = {
  82. page: this.pagination.page, // 页数,
  83. limit: this.pagination.limit, // 条数
  84. }
  85. const res = await this.request({ ...parmas, ...this.params })
  86. let list = res.data.map((item) => {
  87. return {
  88. ...item,
  89. }
  90. })
  91. if (isClear) {
  92. this.list = list
  93. } else {
  94. this.list.push(...list)
  95. }
  96. this.loading = false
  97. if (this.pagination.page * this.pagination.limit >= res.count) {
  98. this.noData = true;
  99. } else {
  100. this.noData = false;
  101. }
  102. }
  103. },
  104. watch: {
  105. params: {
  106. handler() {
  107. this.pagination.page = 1;
  108. this.loadData(true)
  109. },
  110. deep: true,
  111. immediate: false
  112. }
  113. },
  114. };
  115. </script>
  116. <style lang="less" scoped>
  117. .bottom_text {
  118. text-align: center;
  119. color: #969799;
  120. font-size: 14px;
  121. }
  122. </style>