开发移动端 webApp 经常会遇到列表页需要下拉刷新(pull-down)和上拉加载更多(pull-up)的场景,这里介绍一下使用 Vue.js 开发时配合 Mint-UI 的 <Loadmore /> 组件实现这一功能。

Mint UI 的文档写的还是比较详细的,如果有文档看不懂地方,结合github上源代码具体实现喝issue提问,基本就能解决9成问题了。

根据官方文档介绍,快速安装 Mint Ui,然后引入到页面中。

template如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<template>
<div class="list">
<x-header>上拉加载,下拉刷新</x-header>
<div class="page-loadmore-wrapper" ref="wrapper" :style="{ height: wrapperHeight + 'px' }">
<mt-loadmore
:top-method="loadTop"
:bottom-method="loadBottom"
:bottom-all-loaded="allLoaded"
:auto-fill="false"
@top-status-change="handleTopChange"
@bottom-status-change="handleBottomChange"
ref="loadmore">
<ul>
<li class="page-loadmore-listitem" :key="item" v-for="item in list">{{ item }}</li>
</ul>
<div slot="top" class="mint-loadmore-top">
<span v-show="topStatus !== 'loading'" :class="{ 'is-rotate': topStatus === 'drop' }"></span>
<span v-show="topStatus === 'loading'">
<mt-spinner type="snake"></mt-spinner>
</span>
</div>
<div slot="bottom" class="mint-loadmore-bottom">
<span v-show="bottomStatus !== 'loading'" :class="{ 'is-rotate': bottomStatus === 'drop' }"></span>
<span v-show="bottomStatus === 'loading'">
<mt-spinner type="snake"></mt-spinner>
</span>
</div>
</mt-loadmore>
</div>
</div>
</template>

script代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<script>
import { Spinner } from 'mint-ui';

export default {
data() {
return {
list: [],
topStatus: '',
bottomStatus: '',
wrapperHeight: 0,
allLoaded: false,
}
},
components: {
'mt-spinner': Spinner, // 或者使用 Vue.component(Spinner.name, Spinner) 注册组件
'mt-loadmore': Loadmore,
},
methods: {
handleTopChange(status) {
console.log(status);
this.topStatus = status;
},
handleBottomChange(status) {
console.log('handleBottomChange ', status);
this.bottomStatus = status;
},
loadTop() {
console.log('loadTop');
setTimeout(() => {
let firstValue = this.list[0];
for (let i = 1; i <= 10; i++) {
this.list.unshift(firstValue - i);
}
this.$refs.loadmore.onTopLoaded();
console.log('load top end');
}, 2000);
},
loadBottom() {
setTimeout(() => {
let lastValue = this.list[this.list.length - 1];
if (lastValue <= 60) {
for (let i = 1; i <= 10; i++) {
this.list.push(lastValue + i);
}
} else {
this.allLoaded = true; // 若数据已全部获取完毕
}
this.$refs.loadmore.onBottomLoaded();// 固定方法,查询完要调用一次,用于重新定位
console.log('loadBottom end, this.allLoaded = ', this.allLoaded);
}, 1500);
},
},
created() {
for (let i = 0; i < 20; i++) {
this.list.push(i);
}
},
mounted() {
this.wrapperHeight = document.documentElement.clientHeight - this.$refs.wrapper.getBoundingClientRect().top;
}
}
</script>

style代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<style lang="scss">
body {
margin: 0;
background-color: #fafafa;
}
ul,li{ padding:0;margin:0;list-style:none};
.page-loadmore-wrapper {
overflow: scroll; // 很重要
-webkit-overflow-scrolling : touch; // 解决view滑动速度慢或者卡顿问题
}
.page-loadmore-listitem {
height: 50px;
line-height: 50px;
border-bottom: 1px solid #eee;
}
.mint-loadmore-top {
span {
display: inline-block;
transition: .2s linear;
vertical-align: middle;
}
span.is-rotate {
transform: rotate(180deg);
}
}
.mint-loadmore-bottom {
span {
display: inline-block;
transition: .2s linear;
vertical-align: middle;
}
span.is-rotate {
transform: rotate(180deg);
}
}
</style>

预览一下效果:

遇到的问题

  1. pull-up事件loadBottom无法触发,pull-down事件loadTop却正常,原因是因为没有限制<mt-loadmore >的父组件高度,同时也需要给父容器添加overflow:scroll属性
  2. 在手机上测试发现wrapper容器在滑动时有些慢、卡顿的现象,添加css属性-webkit-overflow-scrolling : touch;可解,原因是启用了硬件加速
  3. wrapperHeight高度一定要小于列表的高度才可以pull up