JavaScript分页的制作
做分页按钮的意义:
如果有很多条数据的话不可能一下就把所有的数据都显示出来,这样用户是没有耐心全部看完的,此刻就需要进行分页,比如五条数据一页,更直观的把数据展现出来。
效果图:
HTML部分:
一个简单的表格框架,后续通过拼接字符串往里面拼数据。
box为空div,用来放底部的分页按钮
<div class="content">
<table>
<thead>
<tr>
<td>姓名</td>
<td>年龄</td>
<td>性别</td>
</tr>
</thead>
<tbody>
<tr>
<td>111</td>
<td>222</td>
<td>333</td>
</tr>
</tbody>
</table>
</div>
<div class="box"></div>
css部分:
.box {
position: fixed;
left: 23%;
top: 30%;
border: solid;
width: 55%;
/* background-color: aqua; */
display: flex;
justify-content: space-around;
}
.box input {
width: 20px;
}
.pageNum {
width: 20px;
height: 22px;
text-align: center;
font-weight: 600;
cursor: pointer;
}
.endPage,
.lastPage,
.nextPage,
.homePage {
cursor: pointer;
}
.endPage:hover,
.lastPage:hover,
.nextPage:hover,
.homePage:hover,
.pageNum:hover {
background-color: green;
/* 鼠标悬浮时的背景颜色 */
color: yellow;
/* 鼠标悬浮时的文本颜色 */
}
table {
margin: auto;
border: solid;
text-align: center;
border-collapse: collapse;
width: 280px;
}
table,
th,
td {
padding: 10px;
border: 1px solid black;
/* 为表格、表头和单元格添加 1px 黑色实线边框 */
}
.content {
background-color: darkgray;
width: 305px;
margin: auto;
max-height: 248px;
overflow: auto;
}
Js部分:
let data;
// 每页显示5条
let pageSize = 5;
// 当前页
let selfPage = 0;
// 总页数
let totalPages;
let xhr = new XMLHttpRequest();
xhr.open('get', './js/pages.json', true);
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
let text = xhr.responseText;
data = JSON.parse(text);
render(data); // 数据加载成功后渲染页面
console.log(data);
}
};
function render(data) {
// 计算总页数
//总页数=数据的长度×每页显示的条数,并且向上取整
totalPages = Math.ceil(data.length / pageSize);
console.log(totalPages);
// 内容字符串,后续往里面拼内容
let textStr = '';
//selfPage=0,pageSize=5,0×5=0;(0+1)×5=5
for (let i = selfPage * pageSize; i < (selfPage + 1) * pageSize; i++) {
//因为上面的for循环条件的原因,所以加一个判断
//代表到最后一条数据了,就停止循环
if (i > data.length - 1) {
break;
}
// 拼接data中的name,age,sex数据
textStr += `<tr>
<td>${data[i].name}</td>
<td>${data[i].age}</td>
<td>${data[i].sex}</td>
</tr>`;
}
//把拼接好的字符串放到tbody里
document.getElementsByTagName('tbody')[0].innerHTML = textStr;
// 按钮字符串,后续往里拼分页部分
let butStr = '';
// value 表示当用户选择该选项时,该选项所代表的实际值
butStr += `
<div>第${selfPage + 1}页</div>
<div>共${data.length}条数据</div>
<select id="show" onchange="selectNum()">
<option value="5">5条/页</option>
<option value="10">10条/页</option>
<option value="20">20条/页</option>
</select>
<div class="homePage" onclick="firstPage()">|首页|</div>
<div class="lastPage" onclick="lastPage()">|上一页|</div>
`;
// 分页按钮的逻辑
// 如果总页数小于6的话就生成简单的分页按钮
if (totalPages < 6) {
for (let i = 0; i < totalPages; i++) {
// 当用户点击时.会调用targetPage函数并传i(当前生成的分页按钮所代表的页码)
// 三元判断:如果当前页和i相等就变色
butStr +=
`<div class="pageNum" onclick="targetPage(${i})"${selfPage === i? 'style="background-color:green;"' : ''}>${i + 1}</div>`;
}
// 否则就是大于6页
} else {
// 当前页是前3页的话,就生成前3页和后续页的,分页按钮
if (selfPage < 3) {
butStr += `
<div class="pageNum" onclick="targetPage(${0})" ${selfPage === 0? 'style="background-color:green;"' : ''}>1</div>
<div class="pageNum" onclick="targetPage(${1})" ${selfPage === 1? 'style="background-color:green;"' : ''}>2</div>
<div class="pageNum" onclick="targetPage(${2})" ${selfPage === 2? 'style="background-color:green;"' : ''}>3</div>
<div class="pageNum" onclick="targetPage(${3})">4</div>
<div class="pageNum" onclick="targetPage(${4})">5</div>...`;
// 当前页是最后3页的话,就生成后3页和前面部分页的按钮(在11页点12页的时候,会把14页也渲染出来)
} else if (selfPage >= totalPages - 3) {
// 事件传参为总页数-5,但是显示的页数时总页数-4,
// 少一个是因为传参是数组:从0开始。而显示页数是
butStr +=
`...
<div class="pageNum" onclick="targetPage(${totalPages - 5})">${totalPages - 4}</div>
<div class="pageNum" onclick="targetPage(${totalPages - 4})">${totalPages - 3}</div>
<div class="pageNum" onclick="targetPage(${totalPages - 3})"${selfPage === totalPages - 3? 'style="background-color:green;"' : ''}>${totalPages - 2}</div>
<div class="pageNum" onclick="targetPage(${totalPages - 2})"${selfPage === totalPages - 2? 'style="background-color:green;"' : ''}>${totalPages - 1}</div>
<div class="pageNum" onclick="targetPage(${totalPages - 1})"${selfPage === totalPages - 1? 'style="background-color:green;"' : ''}>${totalPages}</div>`;
//当前页是中间(4-18页)的话,就生成前和后几页的分页按钮(点第4页会显示后面的第6页)
} else {
butStr += `...
<div class="pageNum" onclick="targetPage(${selfPage - 2})">${selfPage - 1}</div>
<div class="pageNum" onclick="targetPage(${selfPage - 1})">${selfPage}</div>
<div class="pageNum" onclick="targetPage(${selfPage})" style="background-color:green">${selfPage + 1}</div>
<div class="pageNum" onclick="targetPage(${selfPage + 1})">${selfPage + 2}</div>
<div class="pageNum" onclick="targetPage(${selfPage + 2})">${selfPage + 3}</div>...`;
}
}
// 底部分页的后半部分
butStr += `
前往<input type="text" class="pages">页
<div class="nextPage" onclick="nextPage()">|下一页|</div>
<div class="endPage" onclick="endPage()">|尾页|</div>
`;
// console.log(butStr);
//把拼好的分页按钮,放到分页的容器里
document.getElementsByClassName('box')[0].innerHTML = butStr;
// 更新下拉框的选中状态,点一页显示多少条数据后会跟着变
document.getElementById('show').value = pageSize;
}
// 点击页码跳转页面
// 在拼接字符串里每一个分页按钮上都绑定了
function targetPage(index) {
//下标等于当前页
selfPage = index;
// 重新调用渲染函数更新一下页面
render(data);
}
// 下一页
function nextPage() {
// 如果当前是最后一页的话 ,就不能在下了
if (selfPage == totalPages - 1) {
alert('我是有底线的');
// 当前页++到第二页
} else {
selfPage++;
}
// 重新调用渲染函数更新一下页面
render(data);
}
// 上一页,和下一页逻辑一样
function lastPage() {
if (selfPage < 0) {
selfPage = 0;
alert('这就是第一页');
} else {
// 当前页--
selfPage--;
}
render(data);
}
// 首页
function firstPage() {
// 让当前页等于0并重新渲染函数更新页面即可
selfPage = 0;
render(data);
}
// 尾页
function endPage() {
//让当前页等于总页数(totalPages - 1)的最后一页
selfPage = totalPages - 1;
render(data);
}
//回车跳转
// 给整个文档上事件监听,键盘事件
document.addEventListener("keydown", function(e) {
// 检查用户按下的是否为回车键
if (e.key === "Enter") {
// 获取input框里的值
let value = document.getElementsByClassName('pages')[0].value.trim();
//增加判断条件
//1. 先将value转为数字Number,在使用Number.isInteget检查是否为整数
// 2.并且把value转为整数(parsInt)并且大于0,防止输入负数
// 3.并且把value转为整数(parsInt)并且小于等于总页数,防止输入超过页数的数
if (Number.isInteger(Number(value)) && parseInt(value) > 0 && parseInt(value) <= totalPages) {
// 令当前页为 转为整数的value-1(因为页是从0开始的,输入的数值是从1开始的.所以-1才更合理)
selfPage = parseInt(value) - 1;
render(data);
} else {
alert('请输入有效数字');
}
// 回车后清空输入框里的值
document.getElementsByClassName('pages')[0].value = '';
}
});
//下拉框的onchange事件
function selectNum() {
//令当前页为0,方便按顺序展示数据
selfPage = 0;
//获取下拉框里的值
let value = document.getElementById('show').value;
//把这个值赋给显示的页数
pageSize = value;
//重新计算总页数:数据长度×现实的页数就是总长度,并向下取整
totalPages = Math.ceil(data.length / pageSize);
render(data);
}
分页中的一些思路及一些复杂的点详解:
分页的逻辑:
总页数小于6的情况:用简单的for循环生成所有的分页按钮(因为数据太少 所以没必要弄的复杂)
if (totalPages < 6) {
for (let i = 0; i < totalPages; i++) {
// 当用户点击时.会调用targetPage函数并传i(当前生成的分页按钮所代表的页码)
// 三元判断:如果当前页和i相等就变色
butStr +=
`<div class="pageNum" onclick="targetPage(${i})"${selfPage === i? 'style="background-color:green;"' : ''}>${i + 1}</div>`;
}
// 否则就是大于6页
}
总页数大于6的情况:(代表数据繁多,需要做分页处理)
前三页:调用页码跳转函数的时候(0)为传的参数,因为下标是从0开始的。而显示内容的时候直接用数字(1)就行
中间页:调用页码跳转函数的时候(当前页数-2)为传的参数,因为下标是从0开始的。而显示内容的时候(当前页-1)为现实的页数,因为页数是从1开始的
后三页:调用页码跳转函数的时候(总页数-6)为传的参数,因为下标是从0开始的。而显示内容的时候(总页数-5)为现实的页数,因为页数是从1开始的
else {
// 当前页是前3页的话,就生成前3页和后续页的,分页按钮
if (selfPage < 3) {
butStr += `
<div class="pageNum" onclick="targetPage(${0})" ${selfPage === 0? 'style="background-color:green;"' : ''}>1</div>
<div class="pageNum" onclick="targetPage(${1})" ${selfPage === 1? 'style="background-color:green;"' : ''}>2</div>
<div class="pageNum" onclick="targetPage(${2})" ${selfPage === 2? 'style="background-color:green;"' : ''}>3</div>
<div class="pageNum" onclick="targetPage(${3})">4</div>
<div class="pageNum" onclick="targetPage(${4})">5</div>...`;
// 当前页是最后3页的话,就生成后3页和前面部分页的按钮(在11页点12页的时候,会把14页也渲染出来)
} else if (selfPage >= totalPages - 3) {
// 事件传参为总页数-5,但是显示的页数时总页数-4,
// 少一个是因为传参是数组:从0开始。而显示页数是
butStr +=
`...
<div class="pageNum" onclick="targetPage(${totalPages - 5})">${totalPages - 4}</div>
<div class="pageNum" onclick="targetPage(${totalPages - 4})">${totalPages - 3}</div>
<div class="pageNum" onclick="targetPage(${totalPages - 3})"${selfPage === totalPages - 3? 'style="background-color:green;"' : ''}>${totalPages - 2}</div>
<div class="pageNum" onclick="targetPage(${totalPages - 2})"${selfPage === totalPages - 2? 'style="background-color:green;"' : ''}>${totalPages - 1}</div>
<div class="pageNum" onclick="targetPage(${totalPages - 1})"${selfPage === totalPages - 1? 'style="background-color:green;"' : ''}>${totalPages}</div>`;
//当前页是中间(4-18页)的话,就生成前和后几页的分页按钮(点第4页会显示后面的第6页)
} else {
butStr += `...
<div class="pageNum" onclick="targetPage(${selfPage - 2})">${selfPage - 1}</div>
<div class="pageNum" onclick="targetPage(${selfPage - 1})">${selfPage}</div>
<div class="pageNum" onclick="targetPage(${selfPage})" style="background-color:green">${selfPage + 1}</div>
<div class="pageNum" onclick="targetPage(${selfPage + 1})">${selfPage + 2}</div>
<div class="pageNum" onclick="targetPage(${selfPage + 2})">${selfPage + 3}</div>...`;
}
}
如何知道有多少页:
1.首先在全局声明总页数(totalPage)和 每页显示几条数据(pageSize=5)
let data;
// 每页显示5条
let pageSize = 5;
// 当前页
let selfPage = 0;
// 总页数
let totalPages;
2.在渲染函数中令: 数据的长度×每页显示的条数=总页数 并向下取整
totalPages = Math.ceil(data.length / pageSize);
分页中如何控制一页显示数据的条数:
1.在拼接字符串中给option设置value
<select id="show" onchange="selectNum()">
<option value="5">5条/页</option>
<option value="10">10条/页</option>
<option value="20">20条/页</option>
</select>
2.然后再给每页显示的条数改为对应的
// 每页显示5条
let pageSize = 5;