1. 程式人生 > >vue - 下拉載入更多

vue - 下拉載入更多

上拉重新整理下拉載入更多

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);
                })
            })
        }
    }
}