背景,項目中經常會出現需要上拉加載更多或者下拉刷新的需求,一直以來呢都是借用各種UI庫來實現,但是不知道啥情況,最近在使用的時候,一直有問題,出不了效果,然人很惱火,於是只能自己動手來實現以下,
這次做得呢也很簡單,只做了上拉加載更多,思路其實很簡單,搞一個組件,然后弄個插槽暴露出去放列表,然后在這個組件上監聽touchstart,move,end等事件
我們一般只需要已經滑到最底部了,在上滑才需要判斷是否加載更多
所以我們需要弄清楚幾個條件
1,是否滑動到最底部了,如果是的話,那么在監聽到上滑,就計算滑動的距離,如果距離達到了閾值,那么就加載更多
在處理加載的過程中,一般會給一些文字提示,比如,login中,已經沒有更多了,...
2,如果沒有滑動到最底部,那么就是普通的頁面滑動,我們不做處理
大體上就是這些,大部分其他的庫會有一些動畫效果,我這里沒加,具體代碼如下:
1 <template> 2 <div class="pull-wrap" @touchstart="start" @touchmove="move" @touchend="end"> 3 <!--上拉加載組件--> 4 <slot ref="pull" class="pull-content"></slot> 5 <p v-if="isMoving" style="font-size: 20px;">pulling....</p> 6 <div class="is-loading" v-if="isLoading"> 7 <img class="loading" src="../assets/images/loading.svg" alt=""> 8 </div> 9 <div class="is-done" v-if="isDone">沒有數據了</div> 10 </div> 11 </template> 12 13 <script> 14 export default { 15 name: 'Pull', 16 props: { 17 onPull: { // 上拉的回調 18 type: Function, 19 require: true 20 } 21 22 }, 23 data() { 24 return { 25 startY: 0, 26 moveY: 0, 27 isMoving: false, 28 isLoading: false, 29 isDone: false, 30 num: 1 // history list的頁數 31 } 32 }, 33 methods: { 34 start(e) { 35 this.startY = e.touches[0].clientY; 36 console.log(this.startY); 37 }, 38 move(e) { 39 if (this.isDone) return 40 console.log('move', e.touches[0].clientY); 41 // 滑動時需要檢測是否到底了,如果還沒到底,就不要loading 42 // if (this.isLoading || this.isDone) return; 43 let flag = this.scrollToTheEnd(); 44 if (flag) { 45 this.isMoving = true 46 } 47 this.moveY = e.touches[0].clientY - this.startY; 48 }, 49 50 end() { 51 // this.isMoving = false 52 if (this.isLoading || this.isDone) return; 53 console.log('touchend', this.moveY); 54 if (this.moveY > -40) { 55 console.log('沒超過', this.moveY); 56 this.isMoving = false; 57 } else { 58 console.log('達到條件了'); 59 let flag = this.scrollToTheEnd(); 60 console.log(flag, '到底了嗎'); 61 if (!flag) return; 62 this.isMoving = false 63 this.num++; 64 this.isLoading = true; 65 this.onPull(this.num); 66 } 67 this.startY = 0; 68 this.moveY = 0; 69 }, 70 71 /** 72 * 判斷滾動條是否到底 73 */ 74 scrollToTheEnd() { 75 let scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop // 滾動的距離 76 let viewHeight = document.documentElement.clientHeight; // 可視區域高度 77 let offsetHeight = document.body.scrollHeight; // 總高度 78 console.log(scrollTop, viewHeight, offsetHeight, '----------------'); 79 // 滾動條到底部的條件 80 return (viewHeight + scrollTop) >= offsetHeight 81 } 82 }, 83 84 mounted() { 85 this.$on('loadEnd', () => { 86 console.log('load完畢了'); 87 this.isLoading = false 88 }) 89 90 this.$on('loadOver', () => { 91 console.log('沒有了'); 92 this.isDone = true; 93 this.isLoading = false; 94 this.isMoving = false; 95 }) 96 97 } 98 } 99 </script> 100 101 <style scoped lang="scss"> 102 /*.pull-wrap{ 103 overflow: hidden; 104 &>.pull-content{ 105 transition: all .4s; 106 } 107 }*/ 108 .pull-wrap{ 109 font-size: 20px; 110 } 111 112 .loading{ 113 width: 50px; 114 height: 50px; 115 } 116 117 </style>
然后使用組件的如下:
<template> <Pull :onPull="pull" ref="pull"> <p v-for="val in list">列表了{{val}}</p>p </Pull> </template> <script> import Pull from '../Pull' methods:{ //這里就是加載更多的處理函數了,這里只是用定時器模擬了一下,需要將加載狀態回傳到子組件中去 pull(num) { console.log('pull回調'); setTimeout(() => { this.num = num; if (this.history_list.length >= this.pk_list_data.others_family_list.length) { console.log('完了'); this.$refs.pull.$emit('loadOver') // 加載完畢 } else { this.$refs.pull.$emit('loadEnd') // 加載完畢 } }, 2000) }, } </script>
這樣,基本就做完了,