Vue移动端下拉刷新和上滑加载攻略
移动端下拉刷新和上滑加载是常见的用户操作需求。在Vue中,我们可以通过一些插件或者自己实现一些组件来完成这些功能。本文将介绍两种实现方式——使用Mint-UI组件和自己实现。
使用Mint-UI实现下拉刷新和上滑加载
Mint-UI是饿了么前端团队推出的一套基于Vue的组件库,提供了丰富的移动端组件。其中,它的下拉刷新和上滑加载组件已经封装好了,我们只需要按照文档来使用即可。
1、安装Mint-UI
# 安装 mint-ui
npm install mint-ui -S
# 引入 mint-ui 样式文件,在入口文件中引入
import 'mint-ui/lib/style.css'
2、使用下拉刷新和上滑加载组件
<template>
<div>
<mt-header title="下拉刷新和上滑加载"></mt-header>
<mt-loadmore :auto-fill="false" :bottom-method="loadBottom" :bottom-all-loaded="allLoaded">
<!-- 这里是列表内容 -->
</mt-loadmore>
</div>
</template>
<script>
import { InfiniteScroll, Loadmore, Header } from 'mint-ui';
export default {
components: {
'mt-header': Header,
'mt-loadmore': Loadmore
},
directives: { InfiniteScroll },
data() {
return {
allLoaded: false,
list: []
}
},
methods: {
loadBottom() {
// 这里是上滑加载的逻辑
// 向服务端请求数据
// 更新allLoaded值
}
}
}
</script>
在这个例子中,我们使用了<mt-header>
组件来显示标题,然后使用了<mt-loadmore>
组件来显示列表内容,并使用了组件提供的bottom-method
属性来监听上滑加载事件。当触发上滑事件时,我们在loadBottom
方法中向服务端请求数据,请求完成后再更新allLoaded
的值,这样就可以完成上滑加载功能了。
3、使用下拉刷新和上滑加载组件注意事项
在使用Mint-UI的下拉刷新和上滑加载组件时,有一些比较重要的注意事项:
- 需要在
created
生命周期函数中调用this.$nextTick()
,否则会出现滚动区域和列表高度不一致的问题; - 需要监听
mounted
生命周期函数和window
对象的resize
事件,以便正确计算滚动区域的高度; - 使用
InfiniteScroll
指令来确保上滑加载事件正确触发。
自己实现下拉刷新和上滑加载
自己实现下拉刷新和上滑加载需要编写大量的代码,但也具有较高的可定制化性和灵活度。
1、确保可以滚动
为了让页面可以滚动,需要在HTML中添加一些必要的CSS样式:
/* 添加以下样式 */
html,
body {
height: 100%;
overflow: hidden;
}
.wrapper {
position: absolute;
height: 100%;
width: 100%;
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
在实际使用时,可以使用Vue的动态class和style来控制wrapper的样式。
2、实现下拉刷新功能
首先,我们需要在wrapper中添加一个列表,并且将其高度设置为屏幕高度。然后,我们需要监听下拉动作,并在下拉释放后执行刷新逻辑:
<template>
<div class="wrapper" ref="wrapper">
<!-- 添加一些列表的DOM结构 -->
</div>
</template>
<script>
export default {
mounted() {
const wrapper = this.$refs.wrapper;
const list = wrapper.querySelector('.list');
const pullDownEl = document.createElement('div');
pullDownEl.className = 'pullDown';
pullDownEl.innerHTML = '<span class="pullDownIcon"></span><span class="pullDownLabel">下拉可以刷新</span>';
list.insertBefore(pullDownEl, list.childNodes[0]);
let startY, endY, moveY, movePoint = [];
let isMove = false;
let pullDownElHeight = 34;
let startTranslate = -pullDownElHeight;
let limitScrollY = 100;
wrapper.addEventListener('touchstart', function (e) {
startY = e.touches[0].clientY;
movePoint = [];
pullDownEl.style.transition = ''
isMove = false;
})
wrapper.addEventListener('touchmove', function (e) {
moveY = e.touches[0].clientY - startY;
if (moveY > 0 && wrapper.scrollTop <= 0) {
if (movePoint.unshift(moveY) > 5) {
isMove = true;
e.preventDefault();
pullDownEl.style.transform = `translate3d(0, ${startTranslate + moveY}px, 0)`
}
}
})
wrapper.addEventListener('touchend', function (e) {
if (isMove) {
pullDownEl.style.transition = 'all .3s';
let translateY = movePoint[0] + startTranslate;
pullDownEl.style.transform = `translate3d(0, ${translateY}px, 0)`
if (translateY > limitScrollY) {
// 这里是刷新逻辑
// 更新列表数据
// 还原元素状态
setTimeout(() => {
pullDownEl.style.transition = 'all .3s';
pullDownEl.style.transform = `translate3d(0, ${startTranslate}px, 0)`
}, 1000)
} else {
setTimeout(() => {
pullDownEl.style.transition = 'all .3s';
pullDownEl.style.transform = `translate3d(0, ${startTranslate}px, 0)`
}, 300)
}
}
})
}
}
</script>
<style>
.wrapper {
// 添加必要的样式
}
.list {
position: relative;
height: 100%;
}
.pullDown {
position: absolute;
top: -34px;
left: 0;
right: 0;
height: 34px;
line-height: 34px;
text-align: center;
font-size: 14px;
color: #999;
transition: all .3s;
}
.pullDownIcon {
display: inline-block;
width: 30px;
height: 30px;
margin-right: 10px;
border-radius: 15px;
background: url('icon-pull-down.png') no-repeat center center;
background-size: 100% 100%;
transform: rotate(180deg);
}
.pullDown.pullDownLoading {
color: #999;
padding-left: 30px;
background:url('icon-loading.png') no-repeat center center;
background-size: 100% 100%;
animation: loading 1.5s linear infinite;
-webkit-animation: loading 1.5s linear infinite;
}
@keyframes loading {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@-webkit-keyframes loading {
from { -webkit-transform: rotate(0deg); }
to { -webkit-transform: rotate(360deg); }
}
</style>
在这个例子中,我们监听了wrapper的touchstart、touchmove、touchend事件,并在事件处理函数中根据不同的状态执行不同的逻辑。当我们下拉到一定距离后,会出现一个提示字样,松开手指可以进行刷新。在刷新完毕后,我们需要还原元素状态,并重新渲染列表。
3、实现上滑加载功能
实现上滑加载的逻辑也比较简单,我们需要在列表末尾添加一个类似“上拉加载更多”的提示,并且监听wrapper的scroll事件,在滑动到达指定位置时触发加载逻辑。
<template>
<div class="wrapper" ref="wrapper" @scroll="onScroll">
<!-- 添加一些列表的DOM结构 -->
<div class="pullUp">
<span class="pullUpIcon"></span>
<span class="pullUpLabel">上拉加载更多</span>
</div>
</div>
</template>
<script>
export default {
data() {
return {
isLoading: false,
isFinished: false,
page: 0,
pageSize: 10,
list: []
}
},
methods: {
loadData() {
if (this.isLoading || this.isFinished) {
return;
}
this.isLoading = true;
fetch(`/api/list?page=${this.page}&pageSize=${this.pageSize}`)
.then(res => res.json())
.then(data => {
this.list = this.list.concat(data);
this.isLoading = false;
this.isFinished = data.length < this.pageSize;
this.page++;
})
.catch(e => {
console.log(e);
this.isLoading = false;
})
},
onScroll(e) {
const el = e.target;
const scrollTop = el.scrollTop;
const height = el.offsetHeight;
const scrollHeight = el.scrollHeight;
if (scrollHeight - scrollTop - height < 20 && !this.isLoading && !this.isFinished) {
this.loadData();
}
}
}
}
</script>
<style>
.wrapper {
// 添加必要的样式
}
.list {
position: relative;
height: 100%;
}
.pullUp {
margin-top: 10px;
text-align: center;
line-height: 30px;
font-size: 14px;
color: #999;
}
.pullUpIcon {
display: inline-block;
width: 30px;
height: 30px;
margin-right: 10px;
border-radius: 15px;
background: url('icon-pull-up.png') no-repeat center center;
background-size: 100% 100%;
transform: rotate(180deg);
}
.pullUp.pullUpLoading {
color: #999;
padding-left: 30px;
background:url('icon-loading.png') no-repeat center center;
background-size: 100% 100%;
animation: loading 1.5s linear infinite;
-webkit-animation: loading 1.5s linear infinite;
}
</style>
在这个例子中,我们监听了wrapper的scroll事件,并在事件处理函数中计算当前滚动位置和高度,并进行判断是否触发上滑加载逻辑。在加载完成后,我们需要更新列表数据,并在判断是否还有更多数据可以加载。
总结
本文介绍了两种实现下拉刷新和上滑加载功能的方法——使用Mint-UI组件和自己实现。前者可以快速实现功能,但不具有太高的灵活度和可定制性;后者可以自由控制样式和逻辑,但需要编写较多的代码。在实际项目中,可以根据具体情况选择合适的方法来实现这个功能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue移动端下拉刷新和上滑加载 - Python技术站