zoukankan      html  css  js  c++  java
  • 基于better-scroll封装一个上拉加载下拉刷新组件

    1.起因

      上拉加载和下拉刷新在移动端项目中是很常见的需求,遂自己便基于better-scroll封装了一个下拉刷新上拉加载组件.

    2.过程

      better-scroll是目前比较好用的开源滚动库,提供很多灵活的api供我们开发各种实用的组件,文档地址(https://ustbhuangyi.github.io/better-scroll/doc/zh-hans/#better-scroll),本次主要用到它提供的pullDownRefresh 和 pullUpLoad api 开启上拉加载和下拉刷新的功能,同时它还提供两个event用于发送请求,pullingUp会在一次上拉加载之后触发,pullingdown 会在一次下拉刷新之后触发,可以在这两个事件中请求数据.这里有一个坑就是,每次上拉或者下拉之后需要调用finishPullUp或finishPullDown来结束这些动作.另外better-scroll在ios系统上快速滚动可能会出现白屏的bug,而且当你滚动暂停的时候回出现抖动,这些可以通过修改配置项useTransition:false解决,better-scroll会开始以js帧动画来渲染滑动效果,以下是代码部分:

    <template>
        <div class="scroll" ref="wrapper">
    
    		<!-- 数据列表 -->
        	<div class="list-wrapper">
        		<slot name="content"></slot>
                <!-- 上拉加载 start-->
                <slot name="pullup">
                    <div class="pullup-wrapper" v-if="pullUpLoad">
                        <div class="before-trigger" v-if="!isPullUpLoad">
                            {{ pullupText }}
                        </div>
                        <div class="after-trigger" v-else>
                            <loading></loading>
                        </div>
                    </div>
                </slot>
                <!-- 上拉加载 end-->
        	</div>
    
            <!-- 下拉刷新start -->
            <slot name="pulldown">
                <div class="pulldown-wrapper" :style="pullDownStyle">
                    <div class="before-trigger" v-if="beforePullDown">
                        {{ pullDownText }}
                    </div>
                    <div class="after-trigger" v-else>
                        <loading v-if="isPullDown"></loading>
                        <div v-else>刷新成功</div>
                    </div>
                </div>
            </slot>
            <!-- 下拉刷新end -->
    
        </div>
    </template>
    
    <script>
    import Bscroll from 'better-scroll';
    import loading from '../loading/loading.vue';
    export default {
    	componentName : 'scroll',
        components:{
            loading
        },
    	data(){
            return{
                scroll       : null,
                isPullUpLoad : false,  // 上拉正在加载中
                pullUpDirty  : true,   // 是否有新数据
                isPullDown   : false,  // 正在刷新
                beforePullDown: true,  // 未开始下拉刷新
                pullDownStyle : {}
            }
    	},
        mounted(){
            this.initScroll();
        },
        computed:{
            pullupText(){
                const moreText = this.pullUpLoad && this.pullUpLoad.more || '上拉加载更多';
                const noMoreText = this.pullUpLoad && this.pullUpLoad.nomore || '没有更多数据了';
                return this.pullUpDirty && moreText || noMoreText;
            },
            pullDownText(){
                return this.pullDown && this.pullDown.refreshText || '下拉刷新';
            }
        },
        methods:{
            forceUpdate(dirty){
                if(this.pullUpLoad && this.isPullUpLoad){
                    this.pullUpDirty = dirty;
                    this.isPullUpLoad = false;
                    this.finishPullUp();
                    this.refresh();
                }else if(this.pullDown && this.isPullDown){
                    this.isPullDown = false;
                    setTimeout(()=>{       // 让刷新成功停留一段时间
                        this.finishPullDown();   
                        this.refresh();
                    },500)
                }
            },
            initScroll(){
                if(!this.$refs.wrapper){
                    return
                }
                let options = {
                    probeType : this.probeType,
                    click     : this.click,
                    startX    : this.startX,
                    startY    : this.startY,
                    tap       : this.tap,
                    pullUpLoad: this.pullUpLoad,
                    pullDownRefresh: this.pullDown && {  threshold: 50,stop : 50 }
                }
    
                this.scroll = new Bscroll(this.$refs.wrapper, options);
                
                // 代理scrollEnd事件
                if(this.scrollEnd){
                    this.scroll.on('scrollEnd',(pos)=>{
                        this.$emit('scrollEnd', pos)
                    })
                }
                // 代理scroll事件
                if(this.onScroll){
                    this.scroll.on('scroll',(pos)=>{
                        console.log(pos.y);
                        let position = pos.y-50 >= 20 && 20 || pos.y-50;
                        this.$set(this.pullDownStyle, 'top', position + 'px')
                        this.$emit('scroll', pos);
                    })
                }
                // 代理pullingUp事件,在一次上拉加载的动作后.
                if(this.pullUpLoad){
                    this.onPullingUp();
                }
    
                // 代理pullingDown事件,在一次下拉刷新的动作后.
                if(this.pullUpLoad){
                    this.onPullingDown();
                }
            },
            onPullingUp(){
                this.scroll.on('pullingUp',()=>{
                    this.isPullUpLoad = true;
                    this.$emit('pullingUp');
                })
            },
            onPullingDown(){
                this.scroll.on('pullingDown', ()=>{
                    this.beforePullDown = false;
                    this.isPullDown = true;
                    this.$emit('pullingDown');
                })
            },
            refresh(){
                this.scroll && this.scroll.refresh();
            },
            finishPullUp(){
                this.scroll && this.scroll.finishPullUp();
            },
            finishPullDown(){
                this.scroll && this.scroll.finishPullDown();
            }
        },
        watch:{
            list(){
                // 列表有变化刷新,没有变化在父组件调用forceUpdate
                this.forceUpdate(true);
            },
            pullDownStyle:{
                handler(val){
                    if(val.top == '-50px'){
                        this.beforePullDown = true;
                    }
                },
                deep : true
            }
        },
        props : {
            list : {            // 数据源
                type : Array,
                default(){
                    return []
                }
            },
            startX : {          // 横轴方向初始化位置
                type : Number,
                default : 0
            },
            startY : {          // 纵轴方向初始化位置
                type : Number,
                default : 0
            },
            probeType : {       // 实时派发滚动位置的等级
                type : Number,
                default : 3
            },
            click : {           // 开启better-scroll派发的click事件
                type : Boolean,
                default : true,
            },
            tap : {
                type : Boolean, // 开启better-scroll派发的tap事件
                default : false
            },
            scrollEnd : { // 监听滚动到结束位置
                type : Boolean,
                default : false
            },
            pullDown : {     // 是否开启下拉刷新
                type : null,
                default : false
            },
            pullUpLoad : {      // 是否开启上拉加载
                type : null,
                default : false
            }, 
            onScroll : {       // 监听滚动事件
                type : Boolean,
                default : true
            }
        }
        
    }
    </script>
    
    <style scoped  lang="scss">
    .scroll{
         100%;
        height: 100%;
        overflow: scroll;
        position: relative;
    
    }
    .list-wrapper{
         100%;
        min-height: 101%;
    }
    .pulldown-wrapper{
         100%;
        height: 50px;
        position: absolute;
        display: flex;
        align-items : center;
        justify-content : center;
        left: 0;
        top: -50px;
        z-index: 100;
    }
    .pullup-wrapper{
         100%;
        height: 50px;
        display: flex;
        align-items : center;
        justify-content : center;
    }
    </style>
  • 相关阅读:
    .NET MVC AjaxHelper
    .NET MVC HtmlHepler
    堆栈存储的区别
    两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?
    == 和 equals 的区别是什么
    JDK 和 JRE 有什么区别?
    javaInt占几个字节
    java代码如何在没有安装JDK的Windows下运行
    java跨平台的原因
    MyBatis JdbcType 与Oracle、MySql数据类型对应关系详解
  • 原文地址:https://www.cnblogs.com/024-faith/p/9894690.html
Copyright © 2011-2022 走看看