简易分页制作
简易分页功能实现
分页是一种常见的前端功能,特别是在需要展示大量数据时。它通过将数据分割成多个页面,帮助用户更容易浏览并提高页面加载性能。本文将介绍一个简易分页的实现思路及其代码实现,旨在帮助开发者快速理解并实现分页功能。
功能概述
这个示例实现了一个简单的分页功能,包括以下主要功能:
- 数据分页显示:根据每页的条数和当前页显示相应的数据。
- 分页控件:展示当前页信息,并允许用户通过上一页、下一页按钮或直接跳转到指定页面进行浏览。
- 自定义每页显示的条数:用户可以选择每页显示不同条数的数据。
- 跳转页功能:用户可以直接输入页码跳转到指定的页面。
- 警告提示:如果输入的页码超出有效范围,会弹出警告提示。
核心思路
-
数据存储与加载:
- 数据以JSON格式存储,并通过
XMLHttpRequest
请求加载到前端。 - 数据加载完成后,进行分页展示。
- 数据以JSON格式存储,并通过
-
分页计算:
- 根据总数据量和每页数据量,计算出总页数。
- 使用当前页的索引(从0开始)来确定需要展示的数据范围。
-
渲染表格与分页控件:
- 在表格中展示当前页的数据。
- 在底部渲染分页控件,显示当前页数、总页数以及每页显示的条数等信息。
- 动态生成页码链接,根据用户的选择更新页面。
-
用户交互:
- 提供上一页、下一页按钮以及页码跳转功能。
- 用户可以通过选择每页显示的数据条数来调整显示内容。
代码实现
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>简易分页</title>
<style>
/* 表格设置宽高 */
.boxes {
width: 60%;
height: 100%;
margin: auto;
text-align: center;
}
.item {
min-height: 200px;
max-height: 700px;
overflow: auto;
}
/* 设置行高 */
.itemes {
line-height: 200%;
}
/* 底部导航栏 */
.box {
width: 80%;
height: 30px;
display: flex;
margin: 1% auto;
justify-content: space-between;
line-height: 30px;
}
.box>button {
width: 30px;
cursor: pointer;
border: none;
font-size: 20px;
}
.pages>span {
padding: 3px 8px;
cursor: pointer;
}
input {
width: 30px;
margin: 4px;
}
/* 弹出警告窗口 */
.warning {
width: 25%;
height: 50px;
border-radius: 10px;
box-shadow: 1px 2px 10px lightgray;
padding-left: 20px;
position: fixed;
right: 0;
background-color: #fde2e2;
color: #f56c6c;
display: none;
}
.title {
font-weight: 600;
}
</style>
</head>
<body>
<!-- 警告弹出窗 -->
<div class="warning">
<div class="title">
错误
</div>
<div>
没有当前页数,请重新输入
</div>
</div>
<!-- 表格 -->
<div class="item">
<table class="boxes" cellspacing="0">
<thead>
<tr>
<th>id</th>
<th>内容</th>
<th>标题</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<!-- 底部导航栏 -->
<div class="box"></div>
<script>
let k = 0; // 当前页
let data; // 存储数据
let num = 5; // 每页显示的数据条数
let total = 0; // 总页数
let main = document.getElementsByTagName('tbody')[0]; // 获取表格主体
let foot = document.getElementsByClassName('box')[0]; // 获取分页底部
// 创建 XMLHttpRequest 获取数据
let xhr = new XMLHttpRequest();
xhr.open('get', './js/paging.json', true);
xhr.send();
// 当数据请求完成时,处理响应
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
data = JSON.parse(xhr.responseText); // 解析 JSON 数据
console.log(data);
renderTable(); // 渲染表格
}
};
// 渲染表格内容
function renderTable() {
let str = '';
for (let i = k * num; i < (k + 1) * num; i++) {
if (i >= data.length) break; // 防止超出数据范围
str += `
<tr class="itemes">
<td>${data[i].id}</td>
<td>${data[i].name}</td>
<td>${data[i].title}</td>
</tr>`;
}
main.innerHTML = str; // 将内容插入表格
renderPagination(); // 渲染分页
}
// 渲染分页控件
function renderPagination() {
let strs = '';
total = Math.ceil(data.length / num); // 计算总页数
strs += `
<span>第${k + 1}页/共${total}页</span>
<span>当前${num}条/共${data.length}条数据</span>
<select onchange="changeItemsPerPage(value)">
<option value="${num}">${num}条/页</option>
<option value="5">5条/页</option>
<option value="15">15条/页</option>
<option value="30">30条/页</option>
<option value="45">45条/页</option>
<option value="60">60条/页</option>
</select>
<button onclick="previousPage()"> < </button>
<div class="pages">`;
// 生成页码
if (total < 6) {
for (let i = 0; i < total; i++) {
strs += createPageLink(i);
}
} else {
if (k < 3) {
for (let i = 0; i < 5; i++) {
strs += createPageLink(i);
}
strs += `...`;
} else if (k > total - 4) {
strs += `...`;
for (let i = total - 5; i < total; i++) {
strs += createPageLink(i);
}
} else {
strs += `...`;
for (let i = k - 2; i <= k + 2; i++) {
strs += createPageLink(i);
}
strs += `...`;
}
}
strs += `</div>
<button onclick="nextPage()"> > </button>
<span>前往第<input type="text" id="input" onchange="goToPageInput()"/>页</span>
`;
foot.innerHTML = strs;
}
// 创建页码链接
function createPageLink(page) {
return `<span class="tail_page" onclick="goToPage(${page})" ${k === page ? 'style="color:#4DAAFF;"' : ''}>${page + 1}</span>`;
}
// 上一页
function previousPage() {
if (k > 0) {
k--;
renderTable();
}
}
// 下一页
function nextPage() {
if (k < total - 1) {
k++;
renderTable();
}
}
// 改变每页显示条数
function changeItemsPerPage(value) {
num = parseInt(value);
k = 0; // 每次改变每页显示条数时,返回第一页
renderTable();
}
// 跳转到指定页
function goToPageInput() {
let input = document.getElementById('input');
let warn = document.getElementsByClassName('warning')[0]; // 获取警告信息元素
let page = parseInt(input.value); // 获取输入的页码
if (page > 0 && page <= total) {
k = page - 1; // 跳转到指定页面
renderTable();
} else {
warn.style.display = 'block'; // 显示警告信息
input.value = ''; // 清空输入框
setTimeout(() => {
warn.style.display = 'none'; // 隐藏警告信息
}, 3000);
}
}
// 跳转到指定页(点击页码时调用)
function goToPage(page) {
k = page;
renderTable();
}
</script>
</body>
</html>
JSON假数据(可更改):
[{
"id": 1,
"name": "路易威登",
"title": "老花手袋"
},
{
"id": 2,
"name": "Cartier",
"title": "卡地亚猎豹系列"
},
{
"id": 3,
"name": "海瑞温斯顿",
"title": "The One系列"
},
{
"id": 4,
"name": "宝格丽",
"title": "B.zero1系列"
},
{
"id": 5,
"name": "MiuMiu",
"title": "保龄球包"
},
{
"id": 6,
"name": "纪梵希",
"title": "纪梵希热流香水"
},
{
"id": 7,
"name": "古驰",
"title": "Dionysus 酒神包"
},
{
"id": 8,
"name": "YSL圣罗兰",
"title": "小金条1966"
},
{
"id": 9,
"name": "梵克雅宝",
"title": "四叶草手链"
},
{
"id": 10,
"name": "FENDI",
"title": "经典手袋"
},
{
"id": 11,
"name": "DIOR",
"title": "马鞍包"
},
{
"id": 12,
"name": "CHNAEL",
"title": "香奈儿5号"
},
{
"id": 13,
"name": "狐妖小红娘",
"title": "涂山容容"
},
{
"id": 14,
"name": "百妖谱",
"title": "桃夭"
},
{
"id": 15,
"name": "假面超人",
"title": "假面骑士"
},
{
"id": 16,
"name": "眷思量",
"title": "镜玄丽娘"
},
{
"id": 17,
"name": "蜡笔小新",
"title": "野原美冴"
},
{
"id": 18,
"name": "来往不逢人,长歌楚天碧",
"title": "柳宗元"
},
{
"id": 19,
"name": "念天地之悠悠,独怆然而泪下",
"title": "陈子昂"
},
{
"id": 20,
"name": "旧时王谢堂前燕,飞入寻常百姓家",
"title": "白居易乌衣巷"
},
{
"id": 21,
"name": "白日依山尽,黄河入海流",
"title": "王之涣"
},
{
"id": 22,
"name": "君言不得意,归卧南山陲",
"title": "王维"
},
{
"id": 23,
"name": "人生不相见,动如参与商",
"title": "杜甫赠卫八处士"
},
{
"id": 24,
"name": "寒雨连江夜入吴,平明送客楚山孤",
"title": "王昌龄"
},
{
"id": 25,
"name": "海客谈瀛洲,烟涛微茫信难求",
"title": "李白梦游天姥吟留别"
},
{
"id": 26,
"name": "落魄江湖载酒行,楚腰纤细掌中轻",
"title": "杜牧遣怀"
},
{
"id": 27,
"name": "故人具鸡黍,邀我至田家",
"title": "孟浩然"
},
{
"id": 28,
"name": "荡胸生曾云,决眦入归鸟",
"title": "杜甫"
},
{
"id": 29,
"name": "塔势如涌出,孤高耸天宫",
"title": "岑参与高适薛据同登慈恩寺浮图"
},
{
"id": 30,
"name": "臣本布衣,躬耕于南阳",
"title": "诸葛亮"
},
{
"id": 31,
"name": "东临碣石,以观沧海",
"title": "曹操"
},
{
"id": 32,
"name": "小楼昨夜又东风",
"title": "李煜"
},
{
"id": 33,
"name": "沙湖道中遇雨,同行皆狼狈",
"title": "苏轼"
},
{
"id": 34,
"name": "笑谈渴饮匈奴血",
"title": "岳飞"
},
{
"id": 35,
"name": "而来四万八千岁,不与秦塞通人烟",
"title": "蜀道难"
},
{
"id": 36,
"name": "住近湓江地低湿,黄芦苦竹绕宅生",
"title": "琵琶行"
},
{
"id": 37,
"name": "谈笑有鸿儒,而来无白丁",
"title": "陋室铭"
},
{
"id": 38,
"name": "阴风怒号,浊浪排空,日星隐曜",
"title": "岳阳楼记"
},
{
"id": 39,
"name": "闲云潭影日悠悠,物换星移几度秋",
"title": "滕王阁序"
},
{
"id": 40,
"name": "六王毕,四海一,蜀山兀,阿胖出",
"title": "阿房宫赋"
},
{
"id": 41,
"name": "海绵宝宝",
"title": "章鱼哥"
},
{
"id": 42,
"name": "fate",
"title": "阿尔托莉雅.潘德拉贡"
},
{
"id": 43,
"name": "第五人格",
"title": "红夫人"
},
{
"id": 44,
"name": "间谍过家家",
"title": "约尔"
},
{
"id": 45,
"name": "进击的巨人",
"title": "伊雷娜"
},
{
"id": 46,
"name": "及尔偕老,老使我怨",
"title": "氓"
},
{
"id": 47,
"name": "行道迟迟,载渴载饥。",
"title": "采薇"
},
{
"id": 48,
"name": "最是一年春好处,绝胜烟柳满皇都",
"title": "早春呈水部张十八员外"
},
{
"id": 49,
"name": "劝君更尽一杯酒,西出阳关无故人",
"title": "送元二使西安"
},
{
"id": 50,
"name": "明月装饰了你的窗子你装饰了别人的梦",
"title": "断章"
},
{
"id": 51,
"name": "天气你好样的",
"title": "白天晒毁我晚上吹飞我"
},
{
"id": 52,
"name": "超绝混搭风",
"title": "棉袄配睡裤"
},
{
"id": 53,
"name": "再也不玩抽象了",
"title": "第一真的有人拿我当沙贝,第二没人懂我的幽默"
},
{
"id": 54,
"name": "微笑",
"title": "爱笑的人法令纹不会太浅"
},
{
"id": 55,
"name": "我是皇帝",
"title": "啊哈:吾皇万岁万岁万万岁"
}
]