首页 > 技术文章 > vue 上拉刷新组件

ysla 2019-11-09 17:10 原文

  背景,项目中经常会出现需要上拉加载更多或者下拉刷新的需求,一直以来呢都是借用各种UI库来实现,但是不知道啥情况,最近在使用的时候,一直有问题,出不了效果,然人很恼火,于是只能自己动手来实现以下,

  这次做得呢也很简单,只做了上拉加载更多,思路其实很简单,搞一个组件,然后弄个插槽暴露出去放列表,然后在这个组件上监听touchstart,move,end等事件

  我们一般只需要已经滑到最底部了,在上滑才需要判断是否加载更多

  所以我们需要弄清楚几个条件

  1,是否滑动到最底部了,如果是的话,那么在监听到上滑,就计算滑动的距离,如果距离达到了阈值,那么就加载更多

    在处理加载的过程中,一般会给一些文字提示,比如,login中,已经没有更多了,...

  2,如果没有滑动到最底部,那么就是普通的页面滑动,我们不做处理

 

  大体上就是这些,大部分其他的库会有一些动画效果,我这里没加,具体代码如下:

  

  1 <template>
  2     <div class="pull-wrap" @touchstart="start" @touchmove="move" @touchend="end">
  3     <!--上拉加载组件-->
  4       <slot ref="pull" class="pull-content"></slot>
  5       <p v-if="isMoving" style="font-size: 20px;">pulling....</p>
  6       <div class="is-loading" v-if="isLoading">
  7         <img class="loading" src="../assets/images/loading.svg" alt="">
  8       </div>
  9       <div class="is-done" v-if="isDone">没有数据了</div>
 10   </div>
 11 </template>
 12 
 13 <script>
 14   export default {
 15     name: 'Pull',
 16     props: {
 17       onPull: {  // 上拉的回调
 18         type: Function,
 19         require: true
 20       }
 21 
 22     },
 23     data() {
 24       return {
 25         startY: 0,
 26         moveY: 0,
 27         isMoving: false,
 28         isLoading: false,
 29         isDone: false,
 30         num: 1  // history list的页数
 31       }
 32     },
 33     methods: {
 34       start(e) {
 35         this.startY = e.touches[0].clientY;
 36         console.log(this.startY);
 37       },
 38       move(e) {
 39         if (this.isDone) return
 40         console.log('move', e.touches[0].clientY);
 41         // 滑动时需要检测是否到底了,如果还没到底,就不要loading
 42         // if (this.isLoading || this.isDone) return;
 43         let flag = this.scrollToTheEnd();
 44         if (flag) {
 45           this.isMoving = true
 46         }
 47         this.moveY = e.touches[0].clientY - this.startY;
 48       },
 49 
 50       end() {
 51         // this.isMoving = false
 52         if (this.isLoading || this.isDone) return;
 53         console.log('touchend', this.moveY);
 54         if (this.moveY > -40) {
 55           console.log('没超过', this.moveY);
 56           this.isMoving = false;
 57         } else {
 58           console.log('达到条件了');
 59           let flag = this.scrollToTheEnd();
 60           console.log(flag, '到底了吗');
 61           if (!flag) return;
 62           this.isMoving = false
 63           this.num++;
 64           this.isLoading = true;
 65           this.onPull(this.num);
 66         }
 67         this.startY = 0;
 68         this.moveY = 0;
 69       },
 70 
 71       /**
 72        * 判断滚动条是否到底
 73        */
 74       scrollToTheEnd() {
 75         let scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop // 滚动的距离
 76         let viewHeight = document.documentElement.clientHeight;  // 可视区域高度
 77         let offsetHeight = document.body.scrollHeight;  // 总高度
 78         console.log(scrollTop, viewHeight, offsetHeight, '----------------');
 79         // 滚动条到底部的条件
 80         return (viewHeight + scrollTop) >= offsetHeight
 81       }
 82     },
 83 
 84     mounted() {
 85       this.$on('loadEnd', () => {
 86         console.log('load完毕了');
 87         this.isLoading = false
 88       })
 89 
 90       this.$on('loadOver', () => {
 91         console.log('没有了');
 92         this.isDone = true;
 93         this.isLoading = false;
 94         this.isMoving = false;
 95       })
 96 
 97     }
 98   }
 99 </script>
100 
101 <style scoped lang="scss">
102   /*.pull-wrap{
103     overflow: hidden;
104     &>.pull-content{
105      transition: all .4s;
106    }
107   }*/
108   .pull-wrap{
109     font-size: 20px;
110   }
111 
112   .loading{
113     width: 50px;
114     height: 50px;
115   }
116 
117 </style>

然后使用组件的如下:

<template>
  <Pull :onPull="pull" ref="pull">
          <p v-for="val in list">列表了{{val}}</p>p
    </Pull>
</template>  

<script>
import Pull from '../Pull'
methods:{

//这里就是加载更多的处理函数了,这里只是用定时器模拟了一下,需要将加载状态回传到子组件中去
 pull(num) {
        console.log('pull回调');
        setTimeout(() => {
          this.num = num;
          if (this.history_list.length >= this.pk_list_data.others_family_list.length) {
            console.log('完了');
            this.$refs.pull.$emit('loadOver') // 加载完毕
          } else {
            this.$refs.pull.$emit('loadEnd') // 加载完毕
          }

        }, 2000)

      },

}

</script> 

这样,基本就做完了,

推荐阅读