前言
在开发移动端的时候,基本上都会使用到上拉加载下拉刷新这个功能,下面一起来看一下具体该如何实现。
开发环境
- vue
- vue-cli
- better-scroll
- less
开发步骤一
- 通过脚手架创建vue项目,安装better-scroll:npm install better-scroll --save-dev
- 在项目中引入better-scroll对象import Bscroll from ‘better-scroll’
- 安装less:npm install less less-loader --save-dev
- 移动端适配(代码文件:index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
<title>demo</title>
</head>
<body>
<noscript>
<strong>We're sorry but s3_recharge doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
</body>
<script>
//屏幕适配
(function (win, doc) {
if (!win.addEventListener) return;
var html = document.documentElement;
function setFont() {
var html = document.documentElement;
var k = 740;
html.style.fontSize = html.clientWidth / k * 100 + "px";
}
setFont();
setTimeout(function () {
setFont();
}, 300);
doc.addEventListener('DOMContentLoaded', setFont, false);
win.addEventListener('resize', setFont, false);
win.addEventListener('load', setFont, false);
// 禁止缩放
$('head').append('<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" />');
document.documentElement.addEventListener('touchstart', function (event) {
if (event.touches.length > 1) {
event.preventDefault();
}
}, false);
var lastTouchEnd = 0;
document.documentElement.addEventListener('touchend', function (event) {
var now = Date.now();
if (now - lastTouchEnd <= 300) {
event.preventDefault();
}
lastTouchEnd = now;
}, false);
// 解决ios safari无法禁止双指缩放问题
document.addEventListener('gesturestart', function (event) {
event.preventDefault();
});
})(window, document);
</script>
</html>
- 创建重置样式,并在APP.vue文件中引入
html,
body,
#app {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
font-family: 'Microsoft YaHei UI';
box-sizing: border-box;
position: relative;
z-index: -1;
}
h1,
h2,
h3,
h4,
h5,
p,
ul,
li,
button,
a {
padding: 0;
margin: 0;
font-weight: normal;
}
a {
text-decoration: none;
}
ul,
li {
list-style: none;
}
button {
border: none;
outline: none
}
/* 金黄色 */
.golden {
color: #ec9c00;
}
/* 灰色背景色 */
.graybgc {
background-color: #eee;
}
/* 深灰色字体色 */
.graytext {
color: #717171;
}
span {
display: inline-block;
vertical-align: middle;
}
开发步骤二
编写结构代码
<template>
<div class="order-list graybgc">
<div class="order-wrapper" ref="wrapper">
<div
class="order-info"
ref="itemwrapper"
v-show="dealList && dealList.length > 0"
>
<div>
<!-- 刷新提示信息 -->
<div class="top-tip" v-if="isPulldown">
<span>重新加载~</span>
</div>
<div class="order-box" v-for="(item, index) in dealList" :key="index">
<div class="header">
<div class="user-info">
<span class="game-name">王者荣耀</span>
<span class="game-serve">李小萌-微信17区</span>
</div>
<div class="order-status">
<span class="no-play-btn">去支付</span>
</div>
</div>
<div class="info">
<div class="info-img">
<img
src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1583233053177&di=350747e7d50ea15f56c08a0d1441fb01&imgtype=0&src=http%3A%2F%2Fphotocdn.sohu.com%2F20110814%2FImg316287483.jpg"
alt=""
/>
</div>
<div class="info-number">
<div class="title">
每日登录礼包
</div>
<div class="money graytext">
单价:¥20 / 件
</div>
<div class="number graytext">数量:10 件</div>
</div>
</div>
<div class="footer">
<div class="time">
<span class="date">02-10 22:00</span>
</div>
<div class="total-money">
<span class="text">合计:</span>
<div class="money">
<span class="min">¥</span>
<span>200</span>
</div>
</div>
</div>
</div>
<div class="null-box"></div>
<div class="bottom-tip" v-if="isPullup">
{{ canPullup ? "松手加载更多~" : "没有更多数据了~" }}
</div>
<div class="null-box"></div>
</div>
</div>
<div class="order-no" v-if="!dealList || dealList.length == 0">
<div class="img"></div>
<div class="desc">暂时还没您的购买记录哦</div>
</div>
</div>
<div class="order-footer">
当前页面仅提供14天记录查询,如有疑问,请
<a href="#">联系客服</a>
</div>
</div>
</template>
注意下面几个问题:
- 高度问题:当子元素高度小于父元素高度时,不会触发任何下拉行为。那么此时只要控制子元素的高度大于父元素的高度即可。
- better-scroll不能滚动问题,pc端可以滚动,切换到手机端不能滚动:创建ref="wrapper"这个BScroll对象时,就会把子元素的ovflow:scroll给禁止掉,此时我们重新设置子元素的相关属性即可。详解地址
开发步骤二
编写样式代码
<style scoped lang="less">
.order-list {
position: relative;
width: 100%;
min-height: 100%;
padding: 0.25rem 0.4rem 0;
box-sizing: border-box;
.order-wrapper {
height: 90vh;
.order-info {
width: 100%;
height: 91.1vh;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
.top-tip {
margin-top: .2rem;
width: 100%;
height: 0.5rem;
line-height: 0.1rem;
text-align: center;
span {
font-size: 0.2rem;
}
}
.order-box {
background-color: #fff;
padding: 0.15rem 0.3rem;
box-sizing: border-box;
border-radius: 0.05rem;
font-size: 0.2rem;
margin-bottom: 0.3rem;
.header {
display: flex;
justify-content: space-between;
align-items: center;
.user-info {
color: #000;
text-align: left;
.game-name {
margin-right: 0.1rem;
}
}
.order-status {
.no-play-btn {
padding: 0.01rem 0.2rem;
background-color: #ec6f00;
color: #fff;
border-radius: 0.2rem;
margin-left: 0.1rem;
}
}
}
.info {
display: flex;
width: 100%;
padding: 0.1rem 0 0.15rem;
box-sizing: border-box;
border-bottom: 0.02rem solid #d5d5d5;
.info-img {
display: inline-block;
vertical-align: top;
width: 1.1rem;
height: 1.1rem;
background-color: #ec6f00;
text-align: center;
line-height: 1.1rem;
margin-right: 0.2rem;
position: relative;
img {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: inline-block;
width: 0.8rem;
height: 0.8rem;
border-radius: 50%;
}
}
.info-number {
display: inline-block;
vertical-align: top;
height: 1.1rem;
text-align: left;
padding: 0;
margin: 0;
.title {
font-size: 0.28rem;
color: #000;
}
}
}
.footer {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 0.15rem;
.money {
display: inline-block;
vertical-align: middle;
font-size: 0.28rem;
color: #000;
span {
vertical-align: baseline;
}
.min {
font-size: 0.22rem;
}
}
}
}
.null-box {
width: 100%;
height: 1px;
}
.bottom-tip {
text-align: center;
font-size: 0.2rem;
color: #999;
margin-top: -0.2rem;
margin-bottom: 0.3rem;
}
}
.order-no {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%) !important;
width: 4rem;
height: 5rem;
text-align: center;
.img {
width: 1.38rem;
height: 1.8rem;
background-color: #999;
margin: 0 auto;
}
.desc {
margin-top: 0.4rem;
font-size: 0.3rem;
}
}
}
.order-footer {
width: 100%;
height: 0.6rem;
line-height: 0.6rem;
position: fixed;
bottom: 0;
left: 0;
font-size: 0.24rem;
background-color: inherit;
z-index: 1;
text-align: center;
a {
text-decoration: underline;
color: #000;
}
}
}
</style>
开发步骤三
编写js代码
<script>
import BScroll from "better-scroll";
export default {
name: "OrderList",
data() {
return {
isPulldown: false,
isPullup: false,
pageIndex: 1,
dealList: [], //订单记录列表
canPullup: true,
lock: false //避免同一时间多次请求数据
};
},
created() {
this.getOrderList();
this.$nextTick(() => {
this.scorllEvent();
});
},
methods: {
// 下拉刷新上拉加载
scorllEvent() {
this.scroll = new BScroll(this.$refs.wrapper, {
probeType: 1,
click: true
});
this.childScroll = new BScroll(this.$refs.itemwrapper, { // 解决在真机中无法滚动问题
mouseWheel: true,
scrollY: true,
click: true
});
// 滑动过程中事件
this.scroll.on("scroll", pos => {
if (this.lock) return;
if (pos.y > 40) {
this.isPulldown = true;
} else if (pos.y < -45) {
this.isPullup = true;
}
});
//滑动结束松开事件
this.scroll.on("touchEnd", pos => {
if (this.lock) return;
if (pos.y > 40 && this.isPulldown) {
//下拉刷新
this.pageIndex = 1;
this.getOrderList("down");
} else if (pos.y < this.scroll.maxScrollY - 45 && this.isPullup) {
//上拉加载
if (this.canPullup) {
this.pageIndex++;
this.getOrderList("up");
}
}
});
},
// 获取订单列表数据
getOrderList(status) {
let data = [1, 2, 3]; //模拟接口返回的数据
if (data && data.length > 0) {
if (status == "up") {
this.dealList = this.dealList.concat(data);
} else {
this.dealList = data;
}
} else {
if (status == "up") {
this.canPullup = false;
return;
}
}
if (status) {
this.lock = true;
this.scroll.refresh(); // 刷新列表后,重新计算滚动区域高度
this.dataTransition(status);
}
},
// 数据过渡效果
dataTransition(status) {
setTimeout(() => {
this.isPullup = false;
this.isPulldown = false;
this.refreshalert(status);
}, 1000);
},
// 数据刷新/加载成功
refreshalert(status) {
setTimeout(() => {
alert(`${status == "down" ? "刷新成功" : "加载成功"}`);
this.lock = false;
}, 1200);
}
}
};
</script>
尾声
以上便是实现上拉加载下拉刷新功能的详细过程。更高阶的技巧是将该功能封装成一个公共的组件,提供给各个页面使用,这个过程的实现且看下回分解。
点击查看更多内容
2人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦