分页器的难点在于: 页数超过最大页码数时要折叠,而折叠怎么实现呢?
生成器生成分页器的页码序列,包含折叠按钮
期望: genPager(总页数=9,当前页=5,最大页码数=7) --> prev 1 ... 3 4 5 6 7 ... 9 next
使用场景: 分页器组件中 v-for="item of computedPager"
currentPage 可v-model双向绑定,这样页码序列可自动跟新
实现
/*
/*
生成 页码和折叠块的序列, 折叠块包含中间数,以便点击折叠块跳到中间页数
num:总页数
currentPage:当前页
pagerCount: 分页器的最大页码数(限制为奇数)
*/
function* genPager(num, currentPage, pagerCount = 7) {
// 没有折叠,直接生成从1开始数组
if(num<=pagerCount){
yield* Array.from({length:num},(_,i)=>i+1)
return
}
/* 1. 先找临界条件 什么情况下左/右边有剩余 */
let l_remain = currentPage - Math.ceil(pagerCount / 2) > 0
let r_remain = num + 1 - Math.ceil(pagerCount / 2) > currentPage
/* 2. 再找中间的页码, 两边都有折叠时为: ... currentPage-2 currentPage-1 currentPage currentPage+1 currentPage+2 ...*/
let arr = Array.from({ length: pagerCount - 2 }, (_, i) => {
/* 只有一边有剩余 时 中间数组 "靠岸"了,就和和当前页没有关系*/
if (!l_remain && r_remain) return i + 2
if (l_remain && !r_remain)
return i + num - Math.ceil(pagerCount / 2) - 1
return i + currentPage - Math.ceil(pagerCount / 2) + 2
})
/* 3. 生成序列 */
if (l_remain) yield {button:'prev'} // 表示此处应有"上一页"按钮
yield 1
if (l_remain) yield { middle: Math.ceil(arr[0] / 2) }
yield* arr
if (r_remain) yield { middle: Math.ceil((num + arr[arr.length - 1]) / 2) }
yield num
if (r_remain) yield {button:'next'} // 表示此处应有"下一页"按钮
}
/* 测试 */
//console.log([...genPager(5, 5,5)]) //[ 1, 2, 3, 4, 5 ]
// for(let i=1;i<=10;i++){
// console.log([...genPager(10, i)]) // 1 * 3 4 5 6 7 * 10
// }