移动端滚动加载更多组件
前言
之前在移动端需求的时候,有个功能点就是关于滚动加载,滚动到底部以后,自动执行下次请求。本来想着使用公司内部基础组件的,但是发现基础组件没有(内部一般禁止引入一些大公司的组件,风险问题)。
看了其他开源的单组件,写的都挺好的,但是整体代码量较多,内心是存在排斥心理的,所以...
没办法,只能手撸了~
实现
配置
配置 | 默认值 | 备注 |
---|---|---|
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,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") no-repeat; background-size: 12px 12px; -webkit-animation: rotate-loading 0.5s linear forwards infinite; animation: rotate-loading 0.5s linear forwards infinite; } </style>
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于