Vue2.0 实战 之 上啦加载下拉刷新

# Vue 2.0 实现 上啦加载下拉刷新

目前也有很多很多实现的方式,但是个人认为,第三方的包还是蛮不小的,

所以决定弄个小的公共vue插件-上啦加载下拉刷新功能,目前没有压塑前文件大小仅仅4-5k左右的样子,

实现的效果图,仿 app 系统的上啦加载下拉刷新功能

==下拉刷新==

上啦加载下拉刷新1


==上啦加载更多==

上啦加载下拉刷新2

==以及暂无数据==

暂无数据

这里是我的,展示图,下面为代码:


首先,在components组件下创建 pull-refresh.vue文件(核心文件)

<template lang="html">
    <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-show="downFlag === true">加载中……</span>
                </slot>
            </footer>
            <div class="nullData" v-show="dataList.noFlag">暂无更多数据</div>
        </section>
    </div>
</template>
<style lang="less">
    @import url("./less/pull-refresh.less");
</style>
<script>
    export default {
        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,
                startY: 0,
                touching: false,
                infiniteLoading: false,
                downFlag: false, //用来显示是否加载中
            }
        },
        methods: {
            touchStart(e) {
                this.startY = e.targetTouches[0].pageY;
                this.startX = e.targetTouches[0].pageX;
                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) { // in refreshing
                    this.state = 2
                    this.top = this.offset
                    return
                }
                if(this.top >= this.offset) { // do refresh
                    this.refresh()
                } else { // cancel refresh
                    this.state = 0
                    this.top = 0
                }

                //用于判断滑动是否在原地 ----begin
                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;
                }

                //--------end--------

                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;

                console.log(bottom + " __ " + this.offset)

                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)
                }, 1000);
            },
            refreshDone() {
                this.state = 0
                this.top = 0
            },

            infinite() {
                this.infiniteLoading = true

                setTimeout(() => {
                    this.onInfinite(this.infiniteDone);
                }, 2000);
            },

            infiniteDone() {
                this.infiniteLoading = false
            }
        }
    }
</script>

其次,再components下创建less/pull-refresh.less文件(也就是上面核心文件样式)

.yo-scroll {
    font-size: 24px;
    position: absolute;
    top: 80px;
    right: 0;
    bottom: 0;
    left: 0;
    overflow: auto;
    z-index: 100;
    height: auto;
    -webkit-overflow-scrolling: touch;
    .inner {
        position: absolute;
        top: -5rem;
        width: 100%;
        height: auto;
        transition-duration: 300ms;
        .pull-refresh {
            position: relative;
            left: 0;
            top: 0;
            width: 100%;
            height: 5rem;
            display: flex;
            display: -webkit-flex;
            align-items: center;
            justify-content: center;
        }
        .load-more {
            height: 5rem;
            line-height: 5rem;
            display: flex;
            text-align: center;
            align-items: center;
            justify-content: center;
            display: none;
        }
        .nullData {
            //暂无更多数据样式
            font-size: 26px;
            color: #999999;
            height: 100px;
            line-height: 80px;
            text-align: center;
        }
        .down-tip,
        .refresh-tip,
        .up-tip {
            display: none;
        }
        .up-tip:before,
        .refresh-tip:before {
            content: '';
            display: inline-block;
            width: 160px;
            height: 70px;
            background-size: 70% !important;
            position: absolute;
            top: 0;
            left: 20%;
        }
        .up-tip:before {
            background: url(../img/pull-refresh/down-logo.png) no-repeat center;
        }
        .refresh-tip:before {
            background: url(../img/pull-refresh/refresh-logo.gif) no-repeat center;
        }
    }
}

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

最后,也就是使用了

<template>
    <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">
                    <span>{{ item.date }}</span>
                    <span>{{ item.portfolio }}</span>
                    <span :class="{'state0':(item.state===0),'state1':(item.state==1),state2:(item.state===2)}"  >{{ item.drop }}</span>
                </li>
            </ul>
        </v-scroll>
    </div>
</template>
<style lang="less">
    @import "./less/contSingleList.less";
</style>
<script type="text/ecmascript-6">
    export default {
        data() {
            return {
                counter: 1, //当前页
                num: 10, // 一页显示多少条
                pageStart: 0, // 开始页数
                pageEnd: 0, // 结束页数
                listdata: [], // 下拉更新数据存放数组
                scrollData: {
                    noFlag: false //暂无更多数据显示
                }
            }
        },
        components: {
            'v-scroll': require("../../../components/common/pull-refresh")
        },
        mounted: function() {
            this.getList();
        },
        methods: {
            getList() {
                var response = []
                for(let i = 0; i < 20; i++) {
                    response.push({
                        date: "2017-06-1"+i,
                        portfolio: "1.5195"+i,
                        drop: i+"+.00 %" ,
                        state: 1
                    })
                }
                this.listdata = response.slice(0, this.num);
            },
            onRefresh(done) {
                this.getList();

                done(); // call done

            },
            onInfinite(done) {
                this.counter++;
                let end = this.pageEnd = this.num * this.counter;
                let i = this.pageStart = this.pageEnd - this.num;

                let more = this.$el.querySelector('.load-more')
                for(i; i < end; i++) {
                    if(i >= 30) {
                        more.style.display = 'none'; //隐藏加载条
                        //走完数据调用方法
                        this.scrollData.noFlag = true;

                        break;
                    } else {
                        this.listdata.push({
                            date: "2017-06-1"+i,
                            portfolio: "1.5195"+i,
                            drop: i+"+.00 %" ,
                            state: 2
                        })
                        more.style.display = 'none'; //隐藏加载条
                    }
                }
                done();
            }

        }
    }
</script>

费了好几天弄出来的,希望可以帮助大众,同时呢?也希望多提意见!


gitHub地址:

https://github.com/Rkatsiteli/Vue-archive/tree/master/Vue2.0%20%E5%AE%9E%E7%8E%B0%E4%B8%8A%E6%8B%89%E5%8A%A0%E8%BD%BD%E4%B8%8B%E6%8B%89%E5%88%B7%E6%96%B0


参考资料:http://www.cnblogs.com/sichaoyun/p/6647458.html

评论 56
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rkatsiteli

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值