可能情况:
1、一条数据没有
2、到最后一页
3、请求状态: 正在加载、加载完成、没有更多数据
4、上滑触底,获取数据,应避免重复发送请求,所以使用数据锁
5、防抖和节流:还可以禁用、倒计时、模态等方式防止重复发送请求
思路:
1、判断是否还有数据
2、设置锁,锁开正常获取数据,锁关,证明还在请求数据,后面点击操作不做处理
3、设置一个属性,作为判断是否是最后一页的标识,
4、设置一个获取实时url的属性,因为每次请求的数据的页码都不一样,所以整个url都不一样,需要获取到最新的url
5、发送请求,返回结果为空,返回数据一个空对象,返回结果非空,判断是否是最后一页,并设置最后一页的属性值是true/false
6、如果还有数据,请求的起始条数加上每次获取的条数
7、数据累加
8、释放锁
/**
* 分页类不关心细节
* 当用户调用类,请求需要下一页的数据,直接返回数据
* paging 需要保存状态,所以应该要以实例化的形式供调用方调用
*/
import {Http} from "./http";
class Paging {
start
count
url //最原始的url 即没有被覆盖的url
locker = false
req
moreData //是否有更多数据
accumulator //累加的数据,每次获取新数据要和原来的数据进行累加
// 初始方法
// req 传入的对象,这个对象有可能不止一个url 还带有其他的参数
/**
* 初始构造方法
* @param req 传入的对象,这个对象有可能不止一个url 还带有其他的参数
* @param count 每页条数
* @param start 从第几条开始查
*/
constructor(req, count, start = 0) {
this.start = start
this.count = count
this.req = req
this.url = req.url
}
/**
* 业务调用主方法
* @returns {Promise<{item: *[], moreData: boolean, accumulator: *[], empty: boolean}|{item: *, moreData: *, accumulator: *, empty: boolean}>}
*/
async getMoreData() {
// 检查锁的状态,如果锁是锁住的,证明还有别的请求还没返回,其他的请求将不会进行,当请求返回结果之后,应该释放锁
//判断是否还有数据
if (!this.moreData) {
return
}
// 检查是否已经锁了,也就是请求的数据是否已经返回
if (!this._getLocker()) {
return
}
// 真实请求数据
const data = await this._actualGetData()
// 释放锁
this._releaseLocker()
return data
}
/**
* 真实发送请求、判断数据结构(异常处理等情况),返回一个对象
* @returns {Promise<null|{item: [], moreData: boolean, accumulator: [], empty: boolean}|{item: *, moreData: *, accumulator: *, empty: boolean}>}
* @private
*/
async _actualGetData() {
const req = this._getCurrentReq()
let paging = await Http.request(req)
if (!paging) {
return null
}
if (paging.total === 0) {
return {
empty: true,
item: [],
moreData: false, // 是否为最后一页的标识
accumulator: []
}
}
this.moreData = this._moreData(paging.total_page, paging.page)
// 判断是否还有数据
if (this.moreData) {
this.start += this.count
}
this._accumulate(paging.items)
return {
empty: false,
item: paging.items,
moreData: this.moreData, // 是否为最后一页的标识
accumulator: this.accumulator
}
}
/**
* 获取当前的对象,也就是当前返回的数据对象
* @returns {*}
* @private
*/
_getCurrentReq() {
let url = this.url
const params = `start=${this.start}&count=${this.count}`
if (url.indexOf('?') !== -1) {
// 当访问的地址没有包含其他的参数,如 url= v1/spu/latest + '?' + params
url += '&' + params
} else {
// 当访问的地址包含其他的参数,如 url= v1/spu/latest?other=abc + '&' + params
url += '?' + params
}
this.req.url = url
return this.req
}
/**
* 判断是否是最后一页,是否还有数据
* @param totalPage 总页数
* @param pageNum 当前页数,0开始计数
* @returns {boolean}
* @private
*/
_moreData(totalPage, pageNum) {
return pageNum < totalPage - 1
}
/**
* 累加每次请求的数据
* @param items 请求返回的数据
* @private
*/
_accumulate(items) {
this.accumulator = this.accumulator.concat(items)
}
/**
* 获取锁的状态
* @returns {boolean}
* @private
*/
_getLocker() {
// 如果锁是锁住的
if (this.locker) {
return false
}
// 如果锁是开的
this.locker = true
return true
}
/**
* 释放锁
* @private
*/
_releaseLocker() {
this.locker = false
}
}
export {Paging}