zoukankan      html  css  js  c++  java
  • vue版app上下拉加载

    首先把基本的样式写好,这里就略过了,然后引入better-scroll库

    import BScroll from 'better-scroll'

     

    其次,在mounted生命周期实例化scroll,可以获取完数据后再new,也可以先new后,获取完数据调用refresh。

    //是否开启下拉刷新,可传入true或者false,如果需要更多配置可以传入一个对象
     
    pullDownRefresh:{
      threshold:80,
      stop:40
    }
    //是否开启上拉加载,同上,上拉无stop参数,这里需要注意是负数
    pullUpLoad:{
      threshold:-80,
    }
    /**
     *
     * @param threshold 触发事件的阀值,即滑动多少距离触发
     * @param stop 下拉刷新后回滚距离顶部的距离(为了给loading留出一点空间)
     */
     

    对于不同缩放程度的屏幕,还需要乘以对应的缩放比。

    淘宝flexible.js里面其实已经有这个获取屏幕缩放比方法,这里直接从里面拿:

    //在util.js里面加一个方法
    export function getDeviceRatio(){
      var isAndroid = window.navigator.appVersion.match(/android/gi);
      var isIPhone = window.navigator.appVersion.match(/iphone/gi);
      var devicePixelRatio = window.devicePixelRatio;
      var dpr;
      if (isIPhone) {
        // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
        if (devicePixelRatio >= 3) {       
          dpr = 3;
        } else if (devicePixelRatio >= 2){
          dpr = 2;
        } else {
          dpr = 1;
        }
      } else {
        // 其他设备下,仍旧使用1倍的方案
        dpr = 1;
      }
      return dpr
    }
     
    import{ DEVICE_RATIO} from '../base/js/api.js'
    /*获取当前缩放比*/
    const DEVICE_RATIO=getDeviceRatio();
     
     
     /*下拉配置*/
    const DOWN_CONFIG={
     threshold:80*DEVICE_RATIO,
     stop:40*DEVICE_RATIO
    }
    /*上拉配置*/
    const UP_CONFIG={
     threshold:-80*DEVICE_RATIO,
    }
     
    this.scroller = new BScroll(scrollWrap,{
     click:true,
     probeType:3,
     pullDownRefresh:DOWN_CONFIG,
     pullUpLoad:UP_CONFIG
    });
     
    实例化后,接下来就是监听上拉和下拉事件了。betterScroll新增了一些事件,主要的有:
     
    /*下拉事件*/
    this.scroller.on('pullingDown',()=> {});
     
    /*上拉事件*/
    this.scroller.on('pullingUp',()=>{});
     

    触发上拉或者下拉事件后,需要我们调用 this.scroller.finishPullDown() 或者 this.scroller.finishPullUp() 来通知better-scroll事件完成。

    大致的流程是这样的:

    this.scroller.on('pullingDown',()=> {
       
      <!-- 1. 发送请求获取数据 -->
       
      <!-- 2. 获取成功后,通知事件完成 -->
       
      <!-- 3. 修改data数据,在nextTick调用refresh -->
    });
    通常操作完成后都需要我们手动触发refresh方法来重新计算可滚动的距离,因此可以写一个watch监听数据的变化,这样我们只需要改变数据,不用每次操作数据后都调用refresh方法。
    watch:{
     dataList(){
      this.$nextTick(()=>{
       this.scroller.refresh();
      })
     }
    },
     
    如果你使用的版本还是旧的,那可以在on( scroll )事件的时候进行判断来实现功能
    this.scroller.on("scroll",(pos)=>{
      //获取整个滚动列表的高度
      var height=getStyle(scroller,"height");
     
      //获取滚动外层wrap的高度
      var pageHeight=getStyle(scrollWrap,"height");
     
      //触发事件需要的阀值
      var distance=80*DEVICE_RATIO;
     
      //参数pos为当前位置
     
      if(pos.y>distance){
     
        //console.log("下拉");
        //do something
        
      }else if(pos.y-pageHeight<-height-distance){
     
        //console.log("上拉");
        //do something
      }
    为了防止多次触发,需要加2个开关类的东西;
    var onPullUp=true;
    var onPullDown=true;

    每次触发事件时,將对应的开关设置为false, 等操作完成后,再重新设置为true,否则多次下拉或者上拉就会触发多次事件。通过设置开关可以保证每次只有一个事件在进行。

    最后,来封装成一个组件

    <template>
      <div ref="wrapper" class="list-wrapper">
        <div class="scroll-content">   
          <slot></slot>    
        </div>  
      </div>
    </template>

    由于每个页面需要滚动的具体内容都是不一样的,所以用了一个插槽来分发。

    组件需要的参数由父级传入,通过prop来接收并设置默认值

    export default {
     props: {
      dataList:{
       type: Array,
       default: []
      },
      probeType: {
       type: Number,
       default: 3
      },
      click: {
       type: Boolean,
       default: true
      }, 
      pullDownRefresh: {
       type: null,
       default: false
      },
      pullUpLoad: {
       type: null,
       default: false
      }, 
     }
     
    组件挂载后,在事件触发时并不直接处理事件,而是向父级发送一个事件,父级通过在模板v-on接收事件并处理后续的逻辑
    mounted() {
      this.scroll = new BScroll(this.$refs.wrapper, {
          probeType: this.probeType,
          click: this.click,   
          pullDownRefresh: this.pullDownRefresh,
          pullUpLoad: this.pullUpLoad,
        })
     
      this.scroll.on('pullingUp',()=> {
        if(this.continuePullUp){
          this.beforePullUp();
          this.$emit("onPullUp","当前状态:上拉加载");
        }
      });
     
      this.scroll.on('pullingDown',()=> {
        this.beforePullDown();
        this.$emit("onPullDown","当前状态:下拉加载更多");
      });
    }
    父组件在使用时,需要传入配置参数Props以及处理子组件发射的事件,并且用具体的内容并替换掉 slot 标签
    <Scroller
      id="scroll"
      ref="scroll"
      :dataList="filmList"
      :pullDownRefresh="DOWN_CONFIG"
      :pullUpLoad="UP_CONFIG"
      @onPullUp="pullUpHandle"
      @onPullDown="pullDownHandle"
     >
     
      <ul>
         <router-link class="film-list" v-for="(v,i) in filmList" :key="v.id" tag="li" :to='{path:"/film-detail/"+v.id}'>
            <div class="film-list__img">
               <img v-lazy="v.images.small" alt="" />       
            </div>
            <div class="film-list__detail">
              <p class="film-list__detail__title">{{v.title}}</p>
              <p class="film-list__detail__director">导演:{{filterDirectors(v.directors)}}</p>
              <p class="film-list__detail__year">年份:{{v.year}}<span>{{v.stock}}</span></p>
              <p class="film-list__detail__type">类别:{{v.genres.join(" / ")}}<span></span></p>
              <p class="film-list__detail__rank">评分:<span>{{v.rating.average}}分</span></p>
            </div>            
          </router-link>
       </ul>    
     </Scroller>
    父组件可以通过this.$refs.xxx来获取到子组件,可以调用子组件里面的方法;
    computed:{
       scrollElement(){
         return this.$refs.scroll
       }
     }
    完整的scroller组件内容如下
    <template>
      <div ref="wrapper" class="list-wrapper">
        <div class="scroll-content">   
          <slot></slot>
          <div>
            <PullingWord v-show="!inPullUp&&dataList.length>0" :loadingWord="beforePullUpWord"></PullingWord>
            <Loading v-show="inPullUp" :loadingWord='PullingUpWord'></Loading>
          </div>   
        </div>
     
        <transition name="pullDown">
          <Loading class="pullDown" v-show="inPullDown" :loadingWord='PullingDownWord'></Loading>
        </transition>
      </div>
    </template>
     
     
    <script >
     import BScroll from 'better-scroll'
     import Loading from './loading.vue'
     import PullingWord from './pulling-word'
     
     const PullingUpWord="正在拼命加载中...";
     const beforePullUpWord="上拉加载更多";
     const finishPullUpWord="加载完成";
     
     const PullingDownWord="加载中...";
     
     export default {
      props: {
       dataList:{
        type: Array,
        default: []
       },
       probeType: {
        type: Number,
        default: 3
       },
       click: {
        type: Boolean,
        default: true
       }, 
       pullDownRefresh: {
        type: null,
        default: false
       },
       pullUpLoad: {
        type: null,
        default: false
       }, 
      },
      data() {
        return {
          scroll:null,
          inPullUp:false,
          inPullDown:false,
          beforePullUpWord,
          PullingUpWord,
          PullingDownWord,
          continuePullUp:true
        }
      },
        
      mounted() {
        setTimeout(()=>{
          this.initScroll();
     
          this.scroll.on('pullingUp',()=> {
            if(this.continuePullUp){
              this.beforePullUp();
              this.$emit("onPullUp","当前状态:上拉加载");
            }
          });
     
          this.scroll.on('pullingDown',()=> {
            this.beforePullDown();
            this.$emit("onPullDown","当前状态:下拉加载更多");
          });
     
        },20)
         
      },
      methods: {
        initScroll() {
          if (!this.$refs.wrapper) {
            return
          }
          this.scroll = new BScroll(this.$refs.wrapper, {
            probeType: this.probeType,
            click: this.click,   
            pullDownRefresh: this.pullDownRefresh,
            pullUpLoad: this.pullUpLoad,
          })
        },
        beforePullUp(){
          this.PullingUpWord=PullingUpWord;
          this.inPullUp=true;
        },
        beforePullDown(){
          this.disable();
          this.inPullDown=true;
        },
        finish(type){
          this["finish"+type]();
          this.enable();
          this["in"+type]=false;
        },
        disable() {
          this.scroll && this.scroll.disable()
        },
        enable() {
          this.scroll && this.scroll.enable()
        },
        refresh() {
          this.scroll && this.scroll.refresh()
        },
        finishPullDown(){
          this.scroll&&this.scroll.finishPullDown()
        },
        finishPullUp(){
          this.scroll&&this.scroll.finishPullUp()
        },  
      },
          
      watch: {
        dataList() {       
          this.$nextTick(()=>{
            this.refresh();           
          })
        }
      },
      components: {
        Loading,
        PullingWord
      }
     }
     
    </script>
  • 相关阅读:
    [导入]流失
    [导入]喜欢与爱
    [导入]毕业的大学生的100条忠告
    sql 实现从右边查询制定字符出现的位置
    [导入]毕业了
    gridview 实现多字段综合查询
    Java实现图片添加水印文字(左右下角)
    python安装win32api pywin32 后出现 ImportError: DLL load failed
    Asp.net mvc 速度优化 关注Yslow(1)
    WPF 3D中如何选择模型的一部分并维护模型
  • 原文地址:https://www.cnblogs.com/ccotk/p/8003915.html
Copyright © 2011-2022 走看看