背景,项目中经常会出现需要上拉加载更多或者下拉刷新的需求,一直以来呢都是借用各种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>
这样,基本就做完了,