上拉加載需求相信很多做移動端的同學基本都有遇到,當然PC端也是家常便飯。目前項目基本接近尾聲,前后端聯調、真機測試都ok,話說項目需求文檔其實並沒有說要實現上拉加載功能,但是我們領導說這個可以有,可以成為一個小亮點。然后就這么愉快的決定了(冷冷的冰雨在我臉上胡亂的拍 233333333333.。。。)好了,廢話不多扯,奔入今天的主題吧!
接下來就是一坨坨的代碼了。。。
1 <template> 2 <div class="scroll-loadmore" 3 @touchstart="touchStart($event)" 4 @touchmove="touchMove($event)" 5 @scroll="(onInfinite || infiniteLoading) ? onScroll($event) : undefined"> 6 <section class="inner"> 7 <slot></slot> 8 <footer class="load-more"> 9 <slot name="load-more"> 10 <vue-loading v-if="loading" type="spin" color="rgba(0,0,0,0.4)" :size="{ width: '30px', height: '30px' }"></vue-loading> 11 <span v-else>{{loadingText}}</span> 12 </slot> 13 </footer> 14 </section> 15 </div> 16 </template> 17 18 <script type="text/ecmascript-6"> 19 import vueLoading from 'vue-loading-template'; 20 export default { 21 props: { 22 offset: { 23 type: Number, 24 default: 30 25 }, 26 onInfinite: { 27 type: Function, 28 default: undefined, 29 require: false 30 }, 31 loadingText: { 32 type: String 33 }, 34 loading: { 35 type: Boolean, 36 default: true 37 } 38 }, 39 data () { 40 return { 41 startY: 0, 42 startScroll: 0, 43 infiniteLoading: false 44 }; 45 }, 46 methods: { 47 touchStart (e) { 48 this.startY = e.targetTouches[0].pageY; 49 this.startScroll = this.$el.scrollTop || 0; 50 }, 51 touchMove (e) { 52 if (this.$el.scrollTop > 0) { 53 return; 54 } 55 let diff = e.targetTouches[0].pageY - this.startY - this.startScroll; 56 if (diff > 0) e.preventDefault(); 57 }, 58 infinite () { 59 this.infiniteLoading = true; 60 this.onInfinite(this.infiniteDone); 61 }, 62 63 infiniteDone () { 64 this.infiniteLoading = false; 65 }, 66 67 onScroll () { 68 if (this.infiniteLoading) { 69 return; 70 } 71 let outerHeight = this.$el.clientHeight; 72 let innerHeight = this.$el.querySelector('.inner').clientHeight; 73 let scrollTop = this.$el.scrollTop; 74 let infiniteHeight = this.$el.querySelector('.load-more').clientHeight; 75 let bottom = innerHeight - outerHeight - scrollTop; 76 if (bottom < infiniteHeight) this.infinite(); 77 } 78 }, 79 components: { 80 vueLoading 81 } 82 }; 83 </script> 84 85 <style> 86 .scroll-loadmore { 87 position: absolute; 88 top: 0; 89 right: 0; 90 bottom: 0; 91 left: 0; 92 overflow: auto; 93 -webkit-overflow-scrolling: touch; 94 background-color: #f4f4f4; 95 } 96 97 .scroll-loadmore .inner { 98 position: absolute; 99 top: 0; 100 width: 100%; 101 transition-duration: 300ms; 102 } 103 104 .scroll-loadmore .load-more { 105 height: 1rem; 106 font-size: 0.4rem; 107 display: flex; 108 align-items: center; 109 justify-content: center; 110 } 111 </style>
把上面的代碼直接保存到一個load-more組件里面。當然組件名字隨便命名。接下來就是在你需要實現上拉加載的組件里引用它。代碼如下↓
1 <template> 2 <div> 3 <load-more :on-infinite="onInfinite" 4 :loading-text="loadingText" 5 :loading="loading" 6 v-if="returnCode === '0000'"> 7 <div> 8 <history-detail-list :message="item" v-for="item in downdata"></history-detail-list> 9 </div> 10 </load-more> 11 <load-more class="appointmentListEmpty" :loading="loading" v-else> 12 <div class="listnull"></div> 13 <div class="marginTop10 color909090"> 14 {{desc}} 15 </div> 16 </load-more> 17 <err-msg v-if="modal"></err-msg> 18 </div> 19 </template> 20 21 <script type="text/ecmascript-6"> 22 import loadMore from 'common/loadmore/loadmore'; 23 import errMsg from 'common/err_msg/err_msg'; 24 import historyDetailList from 'components/history_detail_list/history_detail_list'; 25 import { mapGetters } from 'vuex'; 26 const ERR_OK = 200; 27 export default { 28 data () { 29 return { 30 num: '5', // 一次顯示多少條 31 pageNo: 1, // 開始頁數 32 loadingText: '', 33 loading: false, 34 downdata: [], // 上拉更多的數據存放數組 35 returnCode: '', 36 desc: '', 37 modal: false 38 }; 39 }, 40 methods: { 41 onInfinite (done) { 42 this.loading = true; 43 var formdata = { 44 'UserID': this.clientInfomation.user_id, 45 'PageNo': this.pageNo, 46 'Num': this.num 47 }; 48 this.$axios({ 49 method: 'post', 50 url: '請求的后端接口地址', 51 timeout: 超時時間, 52 data: formdata 53 }).then(response => { 54 if (response.status === ERR_OK) { 55 if (response.data.Head.ReturnCode === '0000') { 56 this.returnCode = response.data.Head.ReturnCode; 57 let arr = response.data.Body.RsList; 58 this.downdata = this.downdata.concat(arr); 59 this.pageNo += 1; 60 if (this.num >= arr.length) { 61 this.loading = false; 62 this.loadingText = '沒有更多了'; 66 return; 67 } 68 } else if (response.data.Head.ReturnCode !== '2001' && response.data.Head.ReturnCode !== '0000') { 69 this.desc = response.data.Head.Desc; 70 this.loading = false; 71 } else { 72 this.modal = true; 73 } 74 } 75 done(); 76 }).catch(() => { 77 if (done) { 78 this.$Message.config({ 79 top: 50, 80 duration: 2 81 }); 82 this.$Message.error('請求超時,請重試'); 83 this.$router.push({path: '/myAppointment'}); 84 } 85 }); 86 } 87 }, 88 components: { 89 loadMore, 90 errMsg, 91 'history-detail-list': historyDetailList 92 }, 93 computed: { 94 ...mapGetters(['clientInfomation']) 95 }, 96 created () { 97 this.onInfinite(); 99 } 100 }; 101 </script> 102 103 <style rel="stylesheet/less" lang="less" scoped> 104 @import '../../common/less/reset.less'; 105 106 .appointmentListEmpty { 107 text-align: center; 108 vertical-align: middle; 109 .fs(32); 110 margin-top: 50%; 111 .line-height(50); 112 .listnull { 113 .w(267); 114 .h(283); 115 background: url('../../common/img/listnull.png') no-repeat center center; 116 .background-size(267, 283); 117 margin: 0 auto; 118 .mt(100); 119 } 120 } 121 </style>
趕快把代碼復制到你的項目下跑起來吧,時間充裕可以看看抽離出來的load-more組件代碼,歡迎一起交流學習,有問題和Bug歡迎留言提issure。最后順便說一句,下拉刷新本項目沒有開發,其實這個都是一套的,有時間再完善咯!