移动端滚动加载更多组件
前言
之前在移动端需求的时候,有个功能点就是关于滚动加载,滚动到底部以后,自动执行下次请求。本来想着使用公司内部基础组件的,但是发现基础组件没有(内部一般禁止引入一些大公司的组件,风险问题)。
看了其他开源的单组件,写的都挺好的,但是整体代码量较多,内心是存在排斥心理的,所以...
没办法,只能手撸了~
实现
配置
配置 | 默认值 | 备注 |
---|---|---|
pageIndex | 1 | 分页请求 index |
pageSize | 10 | 分页请求 size |
totalCount | 0 | 分页请求 count |
delay | 500(ms) | 延迟请求 |
bottom | 25 | 滚动条到达底部多少就会自动请求数据 |
fail | False | 请求失败需要让组件知道,为 true,则更改提示 |
failTips | '请求失败,稍候重试!' | 请求失败需要展示的信息 |
原理
监听滚动,当滚动到用户配置的 bottom 时,执行下次请求,当请求完毕,不执行请求。当请求失败时,提示组件请求失败,增加提示失败信息。
代码
<template>
<div
id="loadMore"
class="loadmore"
>
<slot></slot>
<div
class="loadmore-tip"
id="loadTips"
v-if="totalCount > 0 && totalCount >= pageSize"
>
<i
v-show="loadTips=='正在加载中'"
class="loadmore-icon"
></i>
{{loadTips}}
</div>
</div>
</template>
<script>
let timer = null // 不作为响应式变量,提升性能
export default {
props: {
pageIndex: {
type: Number,
default: 1
},
pageSize: {
type: Number,
default: 10
},
totalCount: {
type: Number,
default: 0
},
delay: {
type: [Number],
default: 500
},
// 滚动条到达底部多少就会自动请求数据
bottom: {
type: [Number],
default: 25
},
// 请求失败预防针,测试中发现的这个
fail: {
type: Boolean,
default: false
},
failTips: {
type: String,
default: '请求失败,稍候重试!'
}
},
data () {
return {
loadTips: '正在加载中'
};
},
watch: {
pageIndex () {
this.loadMore()
},
totalCount: {
handler (val, oldval) {
if (val > 0) {
this.loadMore()
}
},
// 首次请求
immediate: true
},
fail (value) {
if (value) {
this.loadTips = this.failTips
}
}
},
methods: {
// 上滑动加载更多
loadMore () {
this.loadTips = '正在加载中';
const {pageSize, pageIndex, totalCount} = this
return new Promise((resolve, reject) => {
window.onscroll = () => {
timer = setTimeout(() => {
if (!document.getElementById('loadTips')) return
const clientHeight = document.documentElement.clientHeight || document.body.clientHeight || 0
const rectBottom = document.getElementById('loadTips').getBoundingClientRect().bottom || 0
if (rectBottom < clientHeight + this.bottom) {
const size = totalCount - pageIndex * pageSize
if (size > 0) {
this.$emit('loadmore', pageIndex + 1)
resolve(true)
} else {
this.loadTips = '没有更多数据了'
resolve(false)
}
clearTimeout(timer)
}
}, this.delay)
}
})
}
},
beforeDestroy () {
clearTimeout(timer)
}
};
</script>
<style lang="scss" scoped>
.loadmore-tip {
color: #aaa;
font-size: 12px;
text-align: center;
height: 40px;
line-height: 40px;
}
@keyframes rotate-loading {
0% {
-webkit-transform: rotate(0);
transform: rotate(0);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-webkit-keyframes rotate-loading {
0% {
-webkit-transform: rotate(0);
transform: rotate(0);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.loadmore-icon {
vertical-align: -2px;
width: 12px;
height: 12px;
display: inline-block;
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAMAAAC5zwKfAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAGzUExURUxpcaSmo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo6Smo7OajWMAAACQdFJOUwDzVSjxAgf0ChUBCd/hpyn6+ai70Qz1uB92XuuOR5xNbnBc0ulZd4eNIdsW/myUA1iBhMgnbQiWb7zsJM/l1hqqFEjOqQ3GrbH4LGQrr/CK49NdjIncrLNiaRtbtRl1771FUHjQj0aQBt5axWCTHeRmt57dnbTyg6vV7eIgEk4mUdcwOvceDgQRiPylmZgL2vNJv00AAAM1SURBVFjDrZl3WxpBEMaPQ3ovKiAKSreABREVLLEbTewaY4mJJb333nvhIwd2jqNzbeYvHnb2d+zd7Du3LxRVPyaPeqK2Mb8sY3n5yG6L9hxNUuJD7Tk57s6URffxiUcthqZoNaoyNUJlbFUIxDW26zN1Q9/eKACnO2jJcEaLU8eX12sontiUmu5P7tD0TrJ/OtVUPGLo5YVzPChMaZhPLmqLB7WL3vmGwnizg5vXweab9+iqi9LRe2b2ih0cuMRj9km6d2un7brZCniYqMfrmmXSLBua+lfWbFiY1Nmu2lmRTSZpOM59b+LDTPJmpFaKKQ0ZMhe/anDJID9tqj4+ugLjq3K+9SVfhRkro1XvSieMWgXsVJ0R5nRWuePXB2AsrBWyRbXrMGtAWTHUBiN9QkWkD+a1VdQzfD8kXJaGYGZZhTtgf8zFhANjW7BnSndhM/nSJ0o51T7Y1yX6AvUnF6fscqjHQNE1QK9clMhwgZoV1ueE/Sa++zwhACer90SfF+TigZHPOcJIvisMEv5FCf2RChHEINPfbhCl10gBaog+6qEXthK6m5IU7ixi4hN8JhvcPC4NOH4Y/pKvGfJr5yiJ8Y39dJWs+C2FFn9yvAtKPOC/HHACj9dFVnweD3iOAE14wGukqhV4QCL9djwedYV0OkTghxwwhAj054BBRODTHPASIpBUzWVEoAUbOIK9ZD32Q/Fhlw16YaNvPXRxQJcvdIGlOpFbAPUbu0lBG/XgAf+SRr+FuGYrxqtIZeG48YAKog+qSTwiwgtnmQVCNHEhjkeEl3YbHpA5VqzhEQOSDj7VAo5mdjUa8DUcHp/H0Ihroo+3dVuBiAN4zVAyFsG6FouYNzGMCSzi6D0g+tCqx/RKmBHEHXdfMO6T7R2PIy2fTvnmVt5MC3GZaT8sqe98nvUd1u4L79dO2w9n+8bPX1/5LPv9IWtIbtNVe6GS3mYMyQNeN9LRXGSZLnuXSi3TJe9ywTJNf+SpPSWmrmrK+sx7m755P9hvnSqxtg0Bvk9b5+RjOwd1AgpohtsYnxHaC3Gte+gMnjN75Z8L9jOPFB3WnJK/P7I/VuUfs0V7TrncmP8jtvO4FdRBjgAAAABJRU5ErkJggg==")
no-repeat;
background-size: 12px 12px;
-webkit-animation: rotate-loading 0.5s linear forwards infinite;
animation: rotate-loading 0.5s linear forwards infinite;
}
</style>
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于