前言
分页器组件经常与Table组件一起使用,所以也算是一个常用的组件吧,这次咱就来碰一碰它。
市面组件分析
老样子还是以市面上的组件来作切入点,这次咱们就选择antd,现对Antd分析如下:
一、当总页码数 <= 5
结论1:
当总也码数 <= 5时,无论你怎么点击分页器里的按钮,它都会全部显示出来
二、当总页码数很多(比如总页数是50)
- 2.1、当选中的页码 < 5时的情况
- 2.2、当选中的页码 >= 5 && <= 46时的情况
- 2.3、当选中的页码 >= 47 && <= 50时的情况
结论2
当页码较多时,需要根据临界值(由开发者自己控制)来做相应的展示。
三、组件实现
我们再来捋一下antd的思路:
- 页码较小时,全部展示
- 页码较多时,根据临界值做相应展示
3.1、伪代码思路
/*
@param { Number } totalData 总数据量
@param { Number } everyPageDataCount 每页渲染多少条数据
@param { Number } currentPage 当前所在页
@description
1、如果totalData <= 10,则全部渲染出来
2、如果totalData > 10, 比如 totalData == 11, 那么此时分为3种情况
2.1、如果此时 currentPage < 5 或者 currentPage >= totalPage - 2,那么此时展现的结果应该是这样:
1 2 3 4 ... 9 10 11
2.2、如果此时 5 <= currentPage < totalPage - 2, 那么此时展现的结果应该是像下面这种形式:
2.2.1、currentPage == 5,1 ... 3 4 5 6 7 ... 11
2.2.2、currentPage == 6,1 ... 4 5 6 7 8 ... 11
2.2.3、currentPage == 7,1 ... 5 6 7 8 9 ... 11
...
看到这有些观众基本上猜出来了,中间的我个数就是currentPage++--得来的
**/
const createPagination = function (totalData, everyPageDataCount, currentPage){
// 得到总页码数
let totalPage = Math.ceil(totalData / everyPageDataCount);
if ( (currentPage < 5) || ( ( currentPage >= totalPage - 1) && (currentPage < totalData) ) ){
// render something
} else {
// 1、初始化中间元素数组
const slidingWindow = [];
// 2、根据currentPage来动态获取中间元素
for (let index = -2; index <= 2; index++){
const text = document.createTextNode(currentPage + index);
const page = document.createElement('div');
page.appendChild(text);
slidingWindow.push(page);
}
// render something
for (let index = 0; index < slidingWindow.length; index++){
document.querySelector('.box').appendChild(slidingWindow[index])
}
}
}
3.2、全部代码
html、css如下:
<! DOCTYPE html>
<html>
<head>
<title>分页器</title>
<meta charset='utf-8'>
<style>
* {
margin: 0;
padding: 0;
}
html, body {
width: 100%;
height: 100%;
}
.prevIcon {
width: 7px;
height: 7px;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
transform: rotate(-45deg);
}
.nextIcon {
width: 10px;
height: 10px;
border-top: 1px solid #ccc;
border-right: 1px solid #ccc;
transform: rotate(45deg);
}
.page {
width: 20px;
height: 20px;
border: 1px solid #ccc;
display: flex;
justify-content: center;
align-items: center;
}
.selectedPage {
border: 1px solid cornflowerblue;
}
</style>
</head>
<body>
<div class = 'pagination'></div>
</body>
</html>
js代码如下:
const createPagination = function (totalData, everyPageDataCount, currentPage){
// 清空box的子元素
document.querySelector('.box').innerHTML = '';
// 得到总页码数
let totalPage = Math.ceil(totalData / everyPageDataCount);
// 渲染dom集合
let renderDomList = [];
// 上一页dom
const prevIcon = document.createElement('div');
prevIcon.classList.add('prevIcon');
const prevDiv = document.createElement('div');
prevDiv.classList.add('page');
prevDiv.classList.add('qianjin');
prevDiv.appendChild(prevIcon);
// 创建下一页dom
const nextIcon = document.createElement('div');
nextIcon.classList.add('nextIcon');
const nextDiv = document.createElement('div');
nextDiv.classList.add('page');
nextDiv.classList.add('houtui');
nextDiv.appendChild(nextIcon);
// 创建省略号1
const ellipsisIcon1 = document.createTextNode('...');
const ellipsisDiv1 = document.createElement('div');
ellipsisDiv1.classList.add('page');
ellipsisDiv1.appendChild(ellipsisIcon1);
// 创建省略号2
const ellipsisIcon2 = document.createTextNode('...');
const ellipsisDiv2 = document.createElement('div');
ellipsisDiv2.classList.add('page');
ellipsisDiv2.appendChild(ellipsisIcon2);
if (totalPage <= 10){
let renderPageList = [];
for (let index = 1; index <= totalPage; index++){
const text = document.createTextNode(index);
const page = document.createElement('div');
page.classList.add('page');
page.appendChild(text);
renderDomList.push(page);
}
renderDomList = [prevDiv].concat(renderPageList, [nextDiv]);
// 渲染dom
for (let index = 0; index < renderDomList.length; index++){
document.querySelector('.box').appendChild(renderDomList[index]);
}
return
}
if ( (currentPage < 5) || ( ( currentPage >= totalPage - 2) && (currentPage < totalData) ) ){
const firstDiv = [];
const finalDiv = [];
for (let index = 1; index <= 4; index++){
const text = document.createTextNode(index);
const page = document.createElement('div');
page.appendChild(text);
page.classList.add('page');
if (index == currentPage){
page.classList.add('selectedPage');
}
firstDiv.push(page);
};
for (let index = totalPage -2 ; index <= totalPage;index++){
const text = document.createTextNode(index);
const page = document.createElement('div');
page.appendChild(text);
page.classList.add('page');
if (index == currentPage){
page.classList.add('selectedPage');
}
finalDiv.push(page);
}
renderDomList = [prevDiv].concat(firstDiv, [ellipsisDiv1], finalDiv, [nextDiv]);
} else {
// 创建第一个页码元素
const firstIcon = document.createTextNode(1);
const firstDiv = document.createElement('div');
firstDiv.classList.add('page');
firstDiv.appendChild(firstIcon);
// 创建最后的页码元素
const finalIcon = document.createTextNode(totalPage);
const finalDiv = document.createElement('div');
finalDiv.classList.add('page');
finalDiv.appendChild(finalIcon);
let slidingWindow = [];
if ( (currentPage + 2) == ( totalPage - 1 )){
slidingWindow = [];
for (let index = -2; index <= 3; index++){
const text = document.createTextNode(currentPage + index);
const page = document.createElement('div');
page.classList.add('page');
if ((currentPage + index) == currentPage){
page.classList.add('selectedPage');
}
page.appendChild(text);
slidingWindow.push(page);
}
renderDomList = [prevDiv].concat([firstDiv], [ellipsisDiv1], slidingWindow, [nextDiv]);
} else {
for (let index = -2; index <= 2; index++){
const text = document.createTextNode(currentPage + index);
const page = document.createElement('div');
page.classList.add('page');
if ((currentPage + index) == currentPage){
page.classList.add('selectedPage');
}
page.appendChild(text);
slidingWindow.push(page);
}
renderDomList = [prevDiv].concat([firstDiv], [ellipsisDiv1], slidingWindow, [ellipsisDiv2], [finalDiv], [nextDiv]);
}
}
// 渲染元素
for (let index = 0; index < renderDomList.length; index++){
document.querySelector('.box').appendChild(renderDomList[index]);
// 监听事件
renderDomList[index].onclick = function (e){
if (e.target.classList.contains('qianjin') || e.target.classList.contains('prevIcon')){
createPagination(totalData, everyPageDataCount, currentPage - 1);
} else if (e.target.classList.contains('houtui') || e.target.classList.contains('nextIcon')){
createPagination(totalData, everyPageDataCount, currentPage + 1);
} else {
createPagination(totalData, everyPageDataCount, Number(e.target.innerText));
}
}
}
}
补充:
别忘记了边界处理,1 和 totalPage 是不可以点击上一页或者下一页噢
最后
1、上面只是提供一个思路
2、写到这忽然有个想法,我是否应该写一个专栏,这个专栏专门服务于组件
3、发现自己的拖延症是真的严重,一篇文章竟然可以拖一周