tm-pullBottom.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. <template>
  2. <view class="tm-pullBottom">
  3. <scroll-view
  4. class="tm-pullBottom-sroll"
  5. :refresher-enabled="disabled"
  6. :refresher-threshold="pullY"
  7. :refresher-triggered="isRefresh"
  8. :scroll-y="true"
  9. refresher-default-style="none"
  10. :lower-threshold="bottomY"
  11. @scrolltolower="pullBottom"
  12. @refresherpulling="onPulling"
  13. @refresherrefresh="onRefresh"
  14. @refresherrestore="onRestore"
  15. @refresherabort="onAbort"
  16. :style="{
  17. height:activeHeight+'px'
  18. }">
  19. <view v-if="bottomLoadding==true" class="tm-pullBottom-top flex-center flex-col">
  20. <view v-if="loading">
  21. <view>
  22. <slot name="pull" v-if="isPullDown==true&&showScrollPic">
  23. <view class="tm-pullBottom-top-icon flex-center pull"
  24. >
  25. <tm-icons :color="color" name="icon-long-arrow-up"></tm-icons>
  26. </view>
  27. <view class="flex-center tm-pullBottom-top-text text-size-n"
  28. :class="[`text-${color}`]">继续下拉刷新</view>
  29. </slot>
  30. <slot name="pullReresh" v-if="isPullDown==false&&showScrollPic">
  31. <view class="tm-pullBottom-top-icon flex-center "
  32. >
  33. <tm-icons :color="color" name="icon-long-arrow-up"></tm-icons>
  34. </view>
  35. <view class="flex-center tm-pullBottom-top-text text-size-n"
  36. :class="[`text-${color}`]" >松开刷新</view>
  37. </slot>
  38. </view>
  39. <tm-loadding v-if="showScrollPic==false" ></tm-loadding>
  40. </view>
  41. </view>
  42. <slot name="default"></slot>
  43. <tm-loadding v-if="bottomLoadding==false&&loading" ></tm-loadding>
  44. </scroll-view>
  45. </view>
  46. </template>
  47. <script>
  48. /**
  49. * 上拉触底刷新
  50. * @property {String|Number} height = [] 默认0,默认0使用父高度。
  51. * @property {Number} pullY = [] 默认80,下拉多长的距离执行刷新。
  52. * @property {Number} bottomY = [] 默认0,离底部多高度多少执行加载
  53. * @property {String} color = [] 默认primary,主题色。
  54. * @property {Boolean} loading = [] 默认 false,,需要loading.sync执行双向绑定,加载状态,true,加载中。false加载完成。
  55. * @property {Boolean} disabled = [] 默认 true,,是否启用下拉刷新,不影响触底刷新功能。
  56. * @property {Boolean} finish = [] 默认 false,是否数据没有了。如果为true,触底后将不会触发刷新操作。
  57. * @property {Function} refresh 当下拉或者触底时,触发此函数。参数e=pull为下拉刷新,bottom为触底刷新。
  58. * @example <tm-pullBottom :loading.sync="loading" @refresh="getdata"></tm-pullBottom>
  59. */
  60. import tmIcons from "@/tm-vuetify/components/tm-icons/tm-icons.vue"
  61. import tmLoadding from "@/tm-vuetify/components/tm-loadding/tm-loadding.vue"
  62. export default {
  63. components:{tmIcons,tmLoadding},
  64. name:"tm-pullBottom",
  65. props:{
  66. // 高度,默认为0时,自动使用父组件的高度.
  67. height: {
  68. type: String | Number,
  69. default: 0
  70. },
  71. pullY:{
  72. type: Number,
  73. default: 80
  74. },
  75. bottomY:{
  76. type: Number,
  77. default: 0
  78. },
  79. color: {
  80. type: String,
  81. default: 'primary'
  82. },
  83. loading:{
  84. type:Boolean,
  85. default:false
  86. },
  87. // 是否没有更多数据了。
  88. finish:{
  89. type:Boolean,
  90. default:false
  91. },
  92. disabled:{
  93. type:Boolean,
  94. default:true
  95. }
  96. },
  97. watch:{
  98. loading:function(newval){
  99. if(newval==false){
  100. // 结束操作。
  101. this.susscess();
  102. }
  103. },
  104. },
  105. data() {
  106. return {
  107. activeHeight: 0,
  108. isRefresh:false,//是否触发了下拉刷新区域。
  109. freshing:false,//是否刷新 中。
  110. showScrollPic:false,//是否拖动了下拉区域,显示图标。停止不显示。
  111. isPullDown:false,//是否下正确的下拉刷新区域。
  112. bottomLoadding:true,//当前是底部还是顶部刷新操作。false为底部。true为顶部。
  113. };
  114. },
  115. computed:{
  116. },
  117. mounted() {
  118. this.guid = uni.$tm.guid();
  119. let t = this;
  120. this.$nextTick(async function() {
  121. this.activeHeight = uni.upx2px(this.height);
  122. if (!this.activeHeight) {
  123. let wsz = await this.$Querey(".tm-pullBottom",this).catch(e=>{})
  124. this.activeHeight = wsz[0].height||150;
  125. }
  126. if(this.loading===true){
  127. this.$emit('update:loading',false)
  128. }
  129. });
  130. },
  131. methods: {
  132. onRefresh(e) {
  133. let t = this;
  134. this.isRefresh = true;
  135. setTimeout(function() {
  136. t.isRefresh = false;
  137. t.showScrollPic = false;
  138. if(t.freshing==true) return;
  139. t.freshing = true;
  140. t.pullChangeOk();
  141. }, 200);
  142. },
  143. onPulling(e){
  144. if(this.loading === false){
  145. this.$emit('update:loading',true)
  146. }
  147. this.bottomLoadding = true;
  148. this.showScrollPic = true;//显示刷新 图标。
  149. let dy = e.target.dy || 0
  150. // #ifdef H5
  151. dy = e.target.deltaY;
  152. // #endif
  153. if(dy < this. pullY){
  154. this.isPullDown = true;
  155. }else{
  156. this.isPullDown = false;
  157. }
  158. },
  159. onAbort(e){
  160. this.$emit('update:loading',false)
  161. this.showScrollPic = false;//显示刷新 图标。
  162. },
  163. onRestore(e){
  164. this.isRefresh = 'restore'; // 需要重置
  165. },
  166. // 结束操作。
  167. susscess(){
  168. this.freshing = false;
  169. this.$emit('update:loading',false)
  170. },
  171. pullChangeOk(){
  172. this.$emit("refresh",'pull')
  173. },
  174. // 触底加载中。
  175. pullBottom(){
  176. if(this.finish) return;
  177. this.bottomLoadding = false;
  178. if(this.loading === false){
  179. this.$emit('update:loading',true)
  180. this.$emit("refresh",'bottom')
  181. }
  182. },
  183. },
  184. }
  185. </script>
  186. <style lang="scss" scoped>
  187. .tm-pullBottom{
  188. height: 100%;
  189. .tm-pullBottom-sroll{
  190. position: relative;
  191. .tm-pullBottom-top{
  192. width: 100%;
  193. position: relative;
  194. .tm-pullBottom-top-icon{
  195. transition: all 0.5s;
  196. &.pull{
  197. transform: rotate(180deg);
  198. }
  199. }
  200. }
  201. }
  202. }
  203. </style>