2-2 防抖、截流与分页细节分析
//1.一条数据没有 空
//2.最后一页, 还有没有更多
//3.累加 1-20、21-40
//4.非分页数据: a. 正在加载 loadding b. 空
分页数据: a.正在加载 b.加载完成 c.没有更多数据
//5.上滑页面触底 加载 避免用户重复发请求 redis
//按钮 button--防抖和截流: 禁用、倒计时、模态loadding、数据锁
//控制 start count : (ES6以后才推出class)以类为核心的思想封装✅、以函数为核心的思想封装.
2-3 Paging对象
/// 新建 utils->paging.js 文件:
class Paging{
// 使用Paging时, 不关注细节: 嗨, 我需要下一页的数据, 你返回给我
// 面向对象的思想
// Paging对象的设计借鉴了Generator(生成器)
// 因为Paging要保持状态, 所以Paging对象要以实例化的方式提供给调用方, 不能以静态的方式. 也就是new Paging
start
count
url
locker = false
constructor(url, count=10, start=0){ //指明初始化加载的信息
this.start = start
this.count = count
this.url = url
}
getMoreData(){
//getLocker:获取锁的状态, 如果是锁着,就停止加载; 相反就加锁
//request
//releaseLocker 放开锁
}
getLocker(){
if(this.locker){
return false
}
this.locker = true
return true
}
releaseLocker(){
this.locker = false
}
}
2-4 编程原则:多用return提前结束函数,少用else
switch case 替代 if else if
多用return , 少用else
2-5 Paging对象 二
class Paging{
start
count
req //跟请求相关的Object对象
locker = false
url //保存原始的url, 方便以后拼接判断
constructor(req, count=10, start=0){
this.start = start
this.count = count
this.req = req
this.url = req.url
}
getMoreData(){
//getLocker:获取锁的状态, 如果是锁着,就停止加载; 相反就加锁
if(!this._getLocker()){
return
}
//request
this._actualGetData()
//releaseLocker 放开锁
this._releaseLocker()
}
// v1/spu/latest?start=0&count=10
_actualGetData(){
Http.request(this.req)
}
//获取当前的req
_getCurrentReq(){
let url = this.url //因为url是一个字符串, 不是对象, 不用担心引用类型的问题(后面的操作不会改变this.url的值)
const params = `start=${this.start}&count=${this.count}`
// url = v1/spu/latest + '?' + params
// url = v1/spu/latest?other=abc+'&'+params
if(url.indexOf('?') !== -1){//判断字符中是否包含 ?
url += '&' + params
}
else{
url += '?' + params
}
this.req.url = url
return this.req
}
_getLocker(){
if(this.locker){
return false
}
this.locker = true
return true
}
_releaseLocker(){
this.locker = false
}
}
2-6 Paging对象 三
class Paging{
start
count
req //跟请求相关的Object对象
locker = false
url //保存原始的url, 方便以后拼接判断
moreData //当前是不是还有更多数据
constructor(req, count=10, start=0){
this.start = start
this.count = count
this.req = req
this.url = req.url
}
getMoreData(){
//getLocker:获取锁的状态, 如果是锁着,就停止加载; 相反就加锁
if(!this._getLocker()){
return
}
//request
this._actualGetData()
//releaseLocker 放开锁
this._releaseLocker()
}
_actualGetData(){
const req = this._getCurrentReq()
let paging = Http.request(req)
if(!paging){ //如果没有返回,则返回空
return null//在 http.js中 统一异常处理方案
}
if(paging.total === 0){
return{
empty: true,
items:[],
moreData: false,
accumulator: []
}
}
this.moreData = this._moreData(paging.total_page, paging.page)
//HashMap: 比较简单的模型
//class: 在js中,如果写复杂应用, 也可以考虑给这个结果单独封装定义一个class, 然后return一个class回去.
//适用于: 如果返回的Object对象还要包含一些方法的话, 优先建议定义一个class,再把实例化后的对象返回回去.
//因为class除了包含数据之外, 还可以包含方法
/*要返回的数据的模型:
return{// 直接return Object对象或class
empty: boolean, //是不是空数据
items: [],//当次请求到的数据
moreData: boolean, //是不是最后一页
accumulator: []//累加器: 累加历史请求到的所有items数据
}
*/
}
//判断是否有moreData(更多数据)
_moreData(totalPage, pageNum){
// 当前页码 pageNum, 从0开始的; totalPage总共多少页.
return pageNum < totalPage-1
}
_getCurrentReq(){
let url = this.url
const params = `start=${this.start}&count=${this.count}`
if(url.indexOf('?') !== -1){
url += '&' + params
}
else{
url += '?' + params
}
this.req.url = url
return this.req
}
_getLocker(){
if(this.locker){
return false
}
this.locker = true
return true
}
_releaseLocker(){
this.locker = false
}
}
2-7 Paging对象 四 (最终效果)
import {Http} from "./http";
class Paging{
start
count
req //跟请求相关的Object对象
locker = false
url //保存原始的url, 方便以后拼接判断
moreData //当前是不是还有更多数据
accumulator //累加器(对象是可以保存状态的)
constructor(req, count=10, start=0){
this.start = start
this.count = count
this.req = req
this.url = req.url
}
async getMoreData(){
if(!this.moreData){//如果没有更多数据了直接return
return
}
//getLocker:获取锁的状态, 如果是锁着,就停止加载; 相反就加锁
if(!this._getLocker()){
return
}
//request
const data = await this._actualGetData()
//releaseLocker 放开锁
this._releaseLocker()
return data
}
async _actualGetData(){
const req = this._getCurrentReq()
let paging = await Http.request(req)
if(!paging){ //如果没有返回,则返回空
return null//在 http.js中 统一异常处理方案
}
if(paging.total === 0){
return{
empty: true,
items:[],
moreData: false,
accumulator: []
}
}
this.moreData = Paging._moreData(paging.total_page, paging.page)
if(this.moreData){
this.start += this.count
}
this._accumulate(paging.items) //调用累加器
return{
empty: false,
items: paging.items,
moreData: this.moreData,
accumulator: this.accumulator
}
}
//操作accumulator对象
_accumulate(items){
this.accumulator = this.accumulator.concat(items)
}
static _moreData(totalPage, pageNum){//判断是否有moreData(更多数据)
return pageNum < totalPage-1
}
_getCurrentReq(){
let url = this.url
const params = `start=${this.start}&count=${this.count}`
if(url.indexOf('?') !== -1){
url += '&' + params
}
else{
url += '?' + params
}
this.req.url = url
return this.req
}
_getLocker(){
if(this.locker){
return false
}
this.locker = true
return true
}
_releaseLocker(){
this.locker = false
}
}
export {
Paging
}
封装完在模型model的spu-paging.js中测试:
import {Paging} from "../utils/paging"
class SpuPaging{
static async getLatestPaging(){
return new Paging(req:{
url:`spu/latest`
},count:3)
}
}
export{
SpuPaging
}
在页面home.js中调用:
async initBottomSpuList(){
const paging = await SpuPaging.getLatestPaging()
const data = paging.getMoreData()
if(!data){
return
}
...
},
网友评论