vue - 下拉載入更多
阿新 • • 發佈:2018-12-03
上拉重新整理下拉載入更多
vue好多外掛可以使用,完成該功能,但是我使用過幾個外掛之後,不知道是不是自己沒有找對方法,都沒有解決我得問題
我出現得情況是,下拉時請求下一頁得資料,但是如果資料條數過多,比如一頁請求10條資料,螢幕太短只能顯示5條資料,那麼再次下拉就不是請求資料,而是想看下面內容~不知道怎麼識別是下拉請求資料啊,還是想看下面的資料~
前兩天發現自己很傻缺,不使用下拉請求資料,直接到最底部再請求資料就好了啊。。。。然後自己原生寫了一個,基本解決了我得問題,只是判斷到最底部後請求資料
這兩天又研究了一下~出現了下面的程式碼
程式碼 myScroll.vue
style樣式是自己隨便寫的,裡面註釋都有寫
<template> <div class="yo-scroll" :class="{'down':(state===0),'up':(state==1),refresh:(state===2),touch:touching}" @touchstart="touchStart($event)" @touchmove="touchMove($event)" @touchend="touchEnd($event)"> <section class="inner" :style="{ transform: 'translate3d(0, ' + top + 'px, 0)' }"> <header class="pull-refresh"> <slot name="pull-refresh"> <span class="down-tip">下拉更新...</span> <span class="up-tip">鬆開重新整理資料...</span> <span class="refresh-tip">載入中……</span> </slot> </header> <slot> </slot> <footer class="load-more"> <slot name="load-more"> <span v-show="downFlag === false">上拉載入更多...</span> <!-- <span v-if="loadMoreTip">載入中...</span> --> </slot> </footer> <div class="nullData" v-show="dataList.noFlag">暫無更多資料</div> </section> </div> </template> <script> export default{ naem:'demo', props: { offset: { type: Number, default: 100 //預設高度 }, enableInfinite: { type: Boolean, default: true }, enableRefresh: { type: Boolean, default: true }, dataList: { default: false, required: false }, onRefresh: { type: Function, default: undefined, required: false }, onInfinite: { type: Function, default: undefined, require: false } }, data(){ return { top: 0, state: 0, startX: 0, //觸控目標在頁面中的x座標 startY: 0, //觸控目標在頁面中的y座標 touching: false, infiniteLoading: false, downFlag: false, //用來顯示是否載入 loadMoreTip:false //資料載入中 } }, methods:{ touchStart(e){ //當手指觸控式螢幕幕時觸發 this.startX = e.targetTouches[0].pageX; this.startY = e.targetTouches[0].pageY; this.startScroll = this.$el.scrollTop || 0; this.touching = true; // this.dataList.noFlag = false; //有更多資料,所以該提示不顯示 this.$el.querySelector('.load-more').style.display = 'block'; //上拉載入更多顯示 }, touchMove(e){ //當手指在螢幕上滑動的時候連續地觸發 if(!this.enableRefresh || this.dataList.noFlag || !this.touching){ return } //給下拉做回彈效果 let diff = e.targetTouches[0].pageY - this.startY - this.startScroll ; if(diff > 0) e.preventDefault() this.top = Math.pow(diff, 0.8) + (this.state === 2 ? this.offset : 0) if(this.state === 2) { // in refreshing return } if(this.top >= this.offset) { this.state = 1 } else { this.state = 0 } let more = this.$el.querySelector('.load-more'); if(!this.top && this.state === 0) { //沒有到頂部 more.style.display = 'block'; } else { more.style.display = 'none'; } }, touchEnd(e){ //當手指從螢幕上離開的時候觸發 // if(!this.enableRefresh) { // return // } this.touching = false ; if(this.state === 2) { // 在重新整理中 this.state = 2 this.top = this.offset return } if(this.top >= this.offset) { //重新整理 this.refresh() } else { // 取消重新整理 this.state = 0 this.top = 0 } //用於判斷滑動是否在原地 // ---------- 開始 -------------- let endX = e.changedTouches[0].pageX, endY = e.changedTouches[0].pageY, dy = this.startY - endY, dx = endX - this.startX; //如果滑動距離太短 if(Math.abs(dx) < 2 && Math.abs(dy) < 2) { console.log("滑動距離太短") return; } // ---------- 結束 -------------- if(!this.enableInfinite || this.infiniteLoading) { return } let outerHeight = this.$el.clientHeight, innerHeight = this.$el.querySelector('.inner').clientHeight, scrollTop = this.$el.scrollTop, ptrHeight = this.onRefresh ? this.$el.querySelector('.pull-refresh').clientHeight : 0, bottom = innerHeight - outerHeight - scrollTop - ptrHeight; if(bottom <= this.offset && this.state === 0){ this.downFlag = true; this.infinite(); //載入 }else{ this.$el.querySelector('.load-more').style.display = 'none'; this.downFlag = false; } }, refresh(){ this.state = 2; this.top = this.offset; setTimeout(() => { this.onRefresh(this.refreshDone) }, 1500); }, refreshDone(){ this.state = 0 this.top = 0 }, infinite() { this.state == 2; this.infiniteLoading = true setTimeout(() => { // this.loadMoreTip = true ; this.onInfinite(this.infiniteDone); }, 1500); }, infiniteDone() { this.infiniteLoading = false } } } </script> <style scoped> .yo-scroll{ font-size: 24px; position: absolute; top: 1rem; left: 0; bottom:0; right:0; overflow: auto; z-index: 100; height: auto; -webkit-overflow-scrolling: touch; } .inner{ position: absolute; /* top:-5rem; */ top:0; left:0; width:100%; height:auto; transition-duration: 300ms; } /* 下拉重新整理 */ .pull-refresh{ position: relative; top:0; left:0; width:100%; height:2rem; display:flex; display: -webkit-flex; justify-content: center; align-items: center; } /* 上拉載入更多 */ .load-more{ width:100%; height:2rem; line-height:2rem; display:flex; display: -webkit-flex; align-items: center; justify-content: center; text-align:center; display:none; } /* 沒有更多資料 */ .nullData{ height:2rem; line-height:2rem; text-align:center; } .down-tip,.refresh-tip,.up-tip { /*隱藏提示語*/ display: none; } .yo-scroll.touch .inner { transition-duration: 0; } .yo-scroll.down .down-tip { display: block; } .yo-scroll.up .up-tip { display: block; } .yo-scroll.refresh .refresh-tip { display: block; } </style>
需要使用上拉載入資料的頁面 index.js
<template> <div id="scrollList"> <div class="contSingleList"> <div class="tabItem"> <slot></slot> </div> <v-scroll :on-refresh="onRefresh" :on-infinite="onInfinite" :dataList="scrollData"> <ul class="listItem"> <li v-for="(item,index) in listdata" :key="index"> {{item.time}} </li> </ul> </v-scroll> </div> </div> </template> <script> import vScroll from './demo' export default{ name:'scrollList', data(){ return{ counter: 1, //當前頁 num: 15, // 一頁顯示多少條 pageStart: 0, // 開始頁數 pageEnd: 0, // 結束頁數 listdata: [], // 下拉更新資料存放陣列 scrollData: { noFlag: false //暫無更多資料顯示 }, } }, components: { 'v-scroll': vScroll }, created(){ this.getlist(); }, methods:{ getlist(){ this.$store.dispatch('scroll/getList',this.counter).then(()=>{ console.log(this.counter); if(this.$store.state.scroll.code == 200){ this.listdata = this.listdata.concat(this.$store.state.scroll.list); if(this.$store.state.scroll.list.length == 0){ let more = this.$el.querySelector('.load-more') more.style.display = 'none'; //隱藏載入條 //走完資料呼叫方法 this.scrollData.noFlag = true; } }else{ this.$toast({ message:this.$store.state.scroll.msg }); } }).catch((e) => { //alert(e); }); }, onRefresh(done) { this.listdata = [] this.counter = 1; this.getlist(); done() // this.onInfinite(done) }, onInfinite(done) { if(this.scrollData.noFlag){ console.log("111") }else{ this.counter ++; this.getlist(); done(); } } } } </script> <style scoped> .listItem{ width:100%; } .listItem li{ width:100%; height:2rem; border:1px solid red; box-sizing: border-box; text-align:center; } </style>
js檔案請求介面
import axios from 'axios'
export default{
namespaced:true,
state:{
code:0,//狀態碼
msg:'',//提示資訊
list:[],//接收陣列
},
mutations:{
mtgetcode(state,data){
state.code = data;
},
mtgetmsg(state,data){
state.msg = data;
},
mtgetlist(state,data){
state.list = data;
},
},
actions:{
getList:function({commit},info){
let token = window.localStorage.getItem('date');
return new Promise((resovle,reject)=>{
axios.get('url?accessToken='+token+'&page='+info).then((res)=>{
const data = res.data;
console.log(data);
commit('mtgetcode',data.code);
commit('mtgetmsg',data.msg);
commit('mtgetlist',data.bill);
resovle(res);
}).catch(error => {
reject(error);
})
})
}
}
}