本组件优势:
1、使用小程序/uniapp原生page滑动,流畅度高于scroll-view组件
2、采用组件方式直接使用,只需在下拉刷新、上拉加载、加载完成时触发组件方法即可
3、包含无数据时空布局展示
4、可自定义下拉刷新、上拉加载样式
5、采用组件的双向绑定v-model
6、完美解决自定义导航后看不到下拉刷新loading的问题
实际效果图
我们在page.json中开启了自定义导航栏属性和下拉刷新属性后
// 开启下拉刷新
"enablePullDownRefresh": true
// 自定义导航栏
"navigationStyle": "custom"
复制代码
此时,页面中的下拉刷新三个小圆点会被我们的导航栏遮盖住,导致用户下拉刷新看不到loading效果,如下图
这样用户体验就不好了,接下来我们看看怎么解决:
1、封装mscroll组件
2、封装组件内下拉刷新、上拉加载、加载完成时方法
3、利用margin-top: -100upx;
在用户下拉刷新之前隐藏我们写的loading
封装mscroll组件
<template>
<div class="mscroll">
<!-- 下拉刷新 -->
<div class="loading pullLoading">
<i class="dot"></i>
</div>
<!-- 内容插槽 -->
<slot/>
<!-- 上拉加载 -->
<div v-if="hasNextPage" class="loading">
<i class="dot"></i>
</div>
<!-- 空布局 -->
<div class="empty" v-if='isEmpty'>
<!-- 自己更换图片哟 -->
<img mode='widthFix' src="../../assets/image/logoPng.png" alt="">
<p>这里什么都没有呀~</p>
</div>
</div>
</template>
<script>
export default {
props: {
value: {
type: Object,
required: true,
default () {
return {
// 当前页码
page: 1,
// 每页条数
pageSize: 10,
// 是否有下一页
hasNextPage: false,
// 数据总数
total: 0
}
}
}
},
data () {
return {
// 下一页
hasNextPage: false,
// 无数据
isEmpty: false,
// 加载中
isLoading: false
}
},
computed: {
// 转换一下pages
pages () {
return this.value
}
},
methods: {
// 下拉刷新
pullRefresh () {
// 加载中
this.isLoading = true
this.$emit('input', {...this.pages, page: 1})
this.$emit('getData')
},
// 上拉加载
loadMore () {
// 无下一页或加载中不加载
if (!this.hasNextPage || this.isLoading) return
// 加载中
this.isLoading = true
this.$emit('input', {...this.pages, page: this.pages.page + 1})
this.$emit('getData')
},
// 加载成功方法
loadSuccess (data) {
// 第一页要回到顶部
if (data.page == 1) {
uni.pageScrollTo({
scrollTop: 0
})
}
// 结束下拉刷新
uni.stopPullDownRefresh()
// 关闭加载中
this.isLoading = false
// 是否有下一页(可根据总页数和当前页数判断)
this.hasNextPage = data.hasNextPage
// 是否有数据
this.isEmpty = !data.total
}
}
}
</script>
<style lang='scss' scoped>
// 加载中动画
@keyframes dotFlashing {
0% {
background-color: #ccc;
}
100% {
background-color: #999;
}
}
.mscroll{
// loading
.loading {
display: flex;
justify-content: center;
align-items: center;
height: 100upx;
overflow: hidden;
&.pullLoading{
// 这里是关键
margin-top: -100upx;
}
// 模拟微信小圆点
.dot {
display: inline-block;
position: relative;
width: 14upx;
height: 14upx;
border-radius: 50%;
background: #999;
animation: dotFlashing 1s infinite linear alternate;
animation-delay: .5s;
&::before {
left: -28upx;
animation: dotFlashing 1s infinite alternate;
animation-delay: 0s;
}
&::after {
left: 28upx;
animation: dotFlashing 1s infinite alternate;
animation-delay: 1s;
}
&::before,
&::after {
content: '';
display: inline-block;
position: absolute;
top: 0;
width: 14upx;
height: 14upx;
border-radius: 50%;
background: #999;
}
}
}
// 空布局
.empty{
margin-top: 280upx;
text-align: center;
img{
width: 180upx;
}
p{
margin-top: 20upx;
color: #999;
font-size: 26upx
}
}
}
</style>
复制代码
使用方式
page.json配置
"pages": [
{
"path": "pages/homePage/index",
"style": {
"navigationBarTitleText": "页面标题", // 页面标题
"enablePullDownRefresh": true, // 开启下拉刷新(必需)
"backgroundTextStyle": "light", // 下拉刷新loading小圆点颜色,白底+白色小圆点可以实现“隐藏”原生小圆点哦
"navigationStyle": "custom", // 自定义导航栏(不自定义导航栏也可以使用本组件哦,只不过就只能使用原生小圆点样式了,无法自定义下拉刷新样式)
"backgroundColor": "#F5F7F9" // 页面背景底色
}
}
]
复制代码
父组件使用
<template>
<!-- 计算出你的导航高度 -->
<div class='index' :style="{'padding-top': '100px'}">
<!-- 自定义导航栏 -->
<nav :style="{height: '100px'}"></nav>
<!-- 列表(pages必传,getData是加载方法) -->
<m-scroll ref='mscroll' v-model="pages" @getData='getData'>
<!-- 列表数据 -->
<ul>
<li v-for="i in list" :key="i">模拟数据 ------------- 第{{i + 1}}条</li>
</ul>
</m-scroll>
</div>
</template>
<script>
import mScroll from './mscroll'
export default {
components: {
mScroll
},
data () {
return {
list: 20,
pages: {
page: 1,
pageSize: 10
}
}
},
// 触发下拉刷新
onPullDownRefresh () {
this.$refs.mscroll.pullRefresh()
},
// 触发上拉加载
onReachBottom () {
this.$refs.mscroll.loadMore()
},
onLoad () {
this.getData()
},
methods: {
getData () {
// 模拟请求
setTimeout(() => {
this.list += 10
const total = 50
const hasNextPage = total != this.list
const data = {
page: this.pages.page, // 需包含页码
total, // 需包含总数
hasNextPage // 需包含是否下一页
}
// 触发加载成功,需包含当前页码、数据总数、是否有下一页
this.$refs.mscroll.loadSuccess(data)
}, 1000)
}
}
}
</script>
<style lang='scss' scoped>
// 自定义导航栏
nav{
background: #446AAD;
position: fixed;
z-index: 10;
left: 0;
top: 0;
right: 0;
}
ul{
li{
padding: 20upx;
border-bottom: 1px solid #eee;
}
}
</style>
复制代码
至此,代码就写完啦,考虑不周或者有bug的地方,还望多多留言告知我哟?!
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END