【前端项目——分页器】手写分页器实现(JS / React)

组件介绍

用了两种方式实现,注释详细~
可能代码写的不够简洁,见谅🙁
在这里插入图片描述
1. 包含内容显示的分页器
网上看了很多实现,很多只有分页器部分,没和内容显示联动。
因此我增加了模拟content的显示,这里模拟了32条数据,通过分页器控制每页的显示。
2. 切换每页显示数目
列举了三种,5,10,20条每页
在这里插入图片描述

3. 输入值后通过enter跳转
做了一个范围保护,如果超出当前范围,会自动变成最大或最小的页码。(做提示也可以,但我不想点提示的确认)
在这里插入图片描述

原生JS实现

1. HTML

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="style.css">
</head><body><div class="content"></div><div class="page"><button class="prev disabled">&lt;&lt;</button><button class="prev disabled">&lt;</button><ul class="page-list"></ul><button class="next">&gt;</button><button class="next">&gt;&gt;</button><select class="page-size"><option value="5">每页显示5条</option><option value="10">每页显示10条</option><option value="20">每页显示20条</option></select><span>跳转到</span><input class="jump-to" type="number" value="1"><span></span></div><script src="script.js"></script>
</body></html>

2.CSS

* {font-size: 16px;margin: 0;padding: 0;
}a {display: inline-block;text-decoration: none;color: #000;padding: 10px 15px;
}.content {display: flex;flex-direction: row;align-items: center;flex-wrap: wrap;padding: 20px;
}.content div {width: 220px;height: 50px;background-color: #78b5e7;margin: 10px;
}.page {display: flex;justify-content: center;align-items: center;gap: 10px;width: 100%;height: 100px;background-color: #f5f5f5;
}.page-list {list-style: none;display: flex;flex-direction: row;
}.prev,
.next,
.page-num {border-radius: 4px;padding: 0;border: 0;cursor: pointer;
}.prev,
.next {padding: 10px 15px;
}.prev:hover,
.next:hover,
.page-num:hover {background-color: #e9e7e7;
}.active {background-color: #bee5fc;
}select {font-size: 16px;padding: 5px 5px;border-radius: 4px;border: 1px solid #ccc;
}.jump-to {font-size: 16px;padding: 5px 5px;border-radius: 4px;width: 35px;border: 1px solid #ccc;
}button:active {background-color: #fff;
}.disabled {color: #b3b3b3;cursor: not-allowed;opacity: 0.6;
}

3. JS

let content = document.querySelector('.content');
let contentNum = 32;
for (let i = 0; i < contentNum; i++) {let div = document.createElement('div');div.innerHTML = i + 1;content.appendChild(div);
}let current = 1; //当前页码,默认是第一页let pagelist = document.querySelector('.page-list');let showpage = document.querySelector('.page-size');
let pagenum = showpage.value; //默认一页显示多少内容
let num = Math.ceil(contentNum / parseInt(pagenum)); //默认显示的页数的页数let prev = document.querySelectorAll('.prev');
let next = document.querySelectorAll('.next');// 展示当前页码的内容
function showContent() {let start = (current - 1) * parseInt(pagenum);let end = start + parseInt(pagenum);for (let i = 0; i < content.children.length; i++) {if (i >= start && i < end) {content.children[i].style.display = 'block';} else {content.children[i].style.display = 'none';}}
}
// 展示页码列表
function showPage() {// 清空原有的超出所需页面数量的页码列表 while (pagelist.children.length > num) {pagelist.removeChild(pagelist.children[num]);}// 补充所需页面数量的页码列表for (let i = pagelist.children.length; i < num; i++) {let li = document.createElement('li');let a = document.createElement('a');a.href = '#' + i;a.innerHTML = i + 1;li.appendChild(a);li.classList.add('page-num');// 高亮默认页码if (i === 0) {li.classList.add('active');}pagelist.appendChild(li);}// 找到要点击的目标元素let targetElement = pagelist.querySelector('li:nth-child(1) a');// 使用click()方法触发点击事件targetElement.click();//显示当前页码的内容showContent();
}
// 按钮状态
function buttonStatus() {// 两个按钮都要取消禁用prev.forEach(function (item) {item.classList.remove('disabled');});next.forEach(function (item) {item.classList.remove('disabled');});// 如果当前页码是第一页,那么上一页和首页按钮都要禁用if (current == 1) {prev[0].classList.add('disabled');prev[1].classList.add('disabled');}// 如果当前页码是最后一页,那么下一页和末页按钮都要禁用else if (current == num) {next[0].classList.add('disabled');next[1].classList.add('disabled');}
}
//默认显示最开始的内容
showPage();// 绑定事件//select改变
showpage.addEventListener('change', function () {// 重新计算页数pagenum = showpage.value;num = Math.ceil(contentNum / parseInt(pagenum));// 超出范围的页码要置为最后一页,否则会报错if (current > num) {current = num;}// 显示当前页码的内容showPage();
});
//点击页码列表
pagelist.addEventListener('click', function (event) {// 点击的是页码列表if (event.target.tagName === 'A') {// 取消当前页码的activepagelist.children[current - 1].classList.remove('active');// 点击的页码会变成activeevent.target.parentNode.classList.add('active');// 更新当前页码current = event.target.innerHTML;// 显示当前页码的内容buttonStatus();showContent();}
}
);
//绑定按钮事件
//如果当前大于1,那么两个prev都不禁用
//如果当前在最后一页,此时下一页禁用,那么点击后要取消下一页的禁用
for (let i = 0; i < prev.length; i++) {prev[i].addEventListener('click', function () {if (current > 1) {//取消当前页码的activepagelist.children[current - 1].classList.remove('active');//如果当前页码是最后一页,那么下一页要取消禁用next.forEach(function (item) {item.classList.remove('disabled');});if (i == 0)//如果是第一个prev,回到第一页current = 1;else//回到上一页current--;//添加active到当前页码pagelist.children[current - 1].classList.add('active');//如果当前页码是第一页,那么上一页要取消禁用if (current === 1) {prev.forEach(function (item) {item.classList.add('disabled');});}}showContent();})
}
//点击下一页
for (let i = 0; i < next.length; i++) {next[i].addEventListener('click', function () {if (current < num) {//取消当前页码的activepagelist.children[current - 1].classList.remove('active');//如果当前页码是第一页,那么上一页要取消禁用prev.forEach(function (item) {item.classList.remove('disabled');});//回到最后一页if (i == 1)current = num;elsecurrent++;//添加active到当前页码pagelist.children[current - 1].classList.add('active');//如果当前页码是最后一页,那么下一页要取消禁用if (current === num) {next.forEach(function (item) {item.classList.add('disabled');})}}showContent();})
}//跳转到指定页码
let jump = document.querySelector('.jump-to');
jump.addEventListener('keydown', function (event) {if (event.keyCode === 13) {// 溢出保护if (event.target.value > pagelist.children.length) {event.target.value = pagelist.children.length;}if (event.target.value < 1) {event.target.value = 1;}// 模拟点击事件let targetElement = pagelist.querySelector('li:nth-child(' + event.target.value + ') a');// 使用click()方法触发点击事件targetElement.click();buttonStatus();showContent();}
});

React实现

还是react方便。。。。😟
在这里插入图片描述

1.jsx

import React, { useEffect, useState } from 'react'
import styles from './App.module.css'export default function App() {//创建大小为32的数组,内容为索引+1const content = Array.from({ length: 32 }, (_, i) => i + 1);const [currentPage, setCurrentPage] = useState([]);//当前页内容const [current, setCurrent] = useState(1);//当前页码const [pagenum, setPagenum] = useState(5);//每页显示条数const num = Math.ceil(content.length / pagenum);//总页数const [previousDisabled, setPreviousDisabled] = useState(true);//上一页按钮是否禁用const [nextDisabled, setNextDisabled] = useState(false);//下一页按钮是否禁用const [inputValue, setInputValue] = useState('');//跳转页码输入框值function showContent() {//显示当前页内容let start = (current - 1) * pagenum;let end = start + pagenum;setCurrentPage(content.slice(start, end));}function buttonStatus() {//按钮状态if (current == 1) {//第一页setPreviousDisabled(true);setNextDisabled(false);}if (current == num) {//最后一页setNextDisabled(true);setPreviousDisabled(false);}if (current != 1 && current != num) {//中间页setPreviousDisabled(false);setNextDisabled(false);}}useEffect(() => {//页面初始化showContent();buttonStatus();}, [current, pagenum]);return (<div style={{ padding: '20px' }}><div className={styles.content}>{// 创建模拟数据内容currentPage.map((item, index) => (<div key={index}>{item}</div>))}</div><div className={styles.page}>{/*  向前按钮 */}<button className={`${styles.prev} ${previousDisabled ? styles.disabled : ''}`}onClick={() => { setCurrent(1) }}>&lt;&lt;</button><button className={`${styles.prev} ${previousDisabled ? styles.disabled : ''}`}onClick={() => { current > 1 ? setCurrent(current - 1) : null }}>&lt;</button>{/*  页码 */}<ul className={styles.pageList}>{Array.from({ length: num }, (_, i) => i + 1).map(item => (<li key={item}className={current === item ? styles.active : ''}onClick={() => {setCurrent(item);}}><a href={`#${item}`}>{item}</a></li>))}</ul>{/* 向后按钮 */}<button className={`${styles.next} ${nextDisabled ? styles.disabled : ''}`}onClick={() => { current < num ? setCurrent(current + 1) : null }}>&gt;</button><button className={`${styles.next} ${nextDisabled ? styles.disabled : ''}`}onClick={() => { setCurrent(num) }}>&gt;&gt;</button>{/* 页面数量选择框 */}<select className={styles.pageSize} onChange={(e) => {setPagenum(parseInt(e.target.value));setCurrent(1);setInputValue(1);}}><option value="5">每页显示5</option><option value="10">每页显示10</option><option value="20">每页显示20</option></select>{/* 跳转页面输入框 */}<span>跳转到</span><input className={styles.jumpTo} type="number" defaultValue={inputValue} value={inputValue}//记录输入框值onChange={(e) => {setInputValue(e.target.value);}}//跳转到指定页码,回车键触发,限制输入范围onKeyDown={(e) => {if (e.key === 'Enter') {//回车键触发let value = parseInt(e.target.value);if (value > num) value = num;//限制输入范围if (value < 1) value = 1;setCurrent(value);//指定页码setInputValue(value);//更新输入框(因为限制输入范围)}}} /><span></span></div></div>)
}

2. CSS

* {font-size: 16px;margin: 0;padding: 0;
}a {display: inline-block;text-decoration: none;color: #000;padding: 10px 15px;
}.content {display: flex;flex-direction: row;align-items: center;flex-wrap: wrap;padding: 20px;
}.content div {width: 220px;height: 50px;background-color: #78b5e7;margin: 10px;
}.page {display: flex;justify-content: center;align-items: center;gap: 10px;width: 100%;height: 100px;background-color: #f5f5f5;
}.page-list {list-style: none;display: flex;flex-direction: row;
}.prev,
.next,
.page-num {border-radius: 4px;padding: 0;border: 0;cursor: pointer;
}.prev,
.next {padding: 10px 15px;
}.prev:hover,
.next:hover,
.page-num:hover {background-color: #e9e7e7;
}.active {background-color: #bee5fc;
}select {font-size: 16px;padding: 5px 5px;border-radius: 4px;border: 1px solid #ccc;
}.jump-to {font-size: 16px;padding: 5px 5px;border-radius: 4px;width: 35px;border: 1px solid #ccc;
}button:active {background-color: #fff;
}.disabled {color: #b3b3b3;cursor: not-allowed;opacity: 0.6;
}
小记

写原生js的时候还是比较慢,后续要加强

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/6431.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

环形链表面试题详解

A. 环形链表1 给你一个链表的头节点 head &#xff0c;判断链表中是否有环. 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置…

【数据结构】第四讲:双向链表

目录 一、链表的分类 二、双向链表的结构及实现 1.带头双向链表的结构 2.创建节点 3.初始化 4.尾插 5.打印 6.头插 7.尾删 8.头删 9.在pos位置之后插入数据 10.删除pos节点 11.查找 12.销毁 个人主页&#xff1a;深情秋刀鱼-CSDN博客 数据结构专栏&#xff1a;数…

虚拟化技术 安装并配置ESXi服务器系统

安装并配置ESXi服务器系统 一、实验目的与要求 1.掌握创建VMware ESXi虚拟机 2.掌握安装VMware ESXi系统 3.掌握配置VMware ESXi系统的管理IP 4.掌握开启VMware ESXi的shell和ssh功能的方法 二、实验内容 1.安装VMware workstation 15或更高版本 2.创建VMware ESXi虚拟…

专业渗透测试 Phpsploit-Framework(PSF)框架软件小白入门教程(三)

本系列课程&#xff0c;将重点讲解Phpsploit-Framework框架软件的基础使用&#xff01; 本文章仅提供学习&#xff0c;切勿将其用于不法手段&#xff01; 继续接上一篇文章内容&#xff0c;讲述如何进行Phpsploit-Framework软件的基础使用和二次开发。 当我们点击 submit 提…

基于t972 Android9 AP6256,如何在设置中添加5G热点选项,并使其正常打开

通过设置的的WiFi热点选项可以知道关键词“2.4GHz”&#xff0c;因此可以其全局搜索&#xff0c;在packages\apps\Settings\res\values\strings.xml文件下找到如下图所示&#xff0c; 从上面注释可以知道&#xff0c;选项按键选择2.4GHz触发的按键关键词是“wifi_ap_choose_2G…

✔ ★Java项目——设计一个消息队列(五)【虚拟主机设计】

虚拟主机设计 创建 VirtualHost实现构造⽅法和 getter创建交换机删除交换机创建队列删除队列创建绑定删除绑定发布消息 ★路由规则1) 实现 route ⽅法2) 实现 checkRoutingKeyValid3) 实现 checkBindingKeyValid4) 实现 routeTopic5) 匹配规则测试⽤例6) 测试 Router 订阅消息1…

分布式websocket IM即时通讯聊天开源项目如何启动

前言 自己之前分享了分布式websocket的视频有同学去fork项目了&#xff0c;自己启动一下更方便理解项目嘛。然后把项目启动需要的东西全部梳理出来。支持群聊单聊,表情包以及发送图片。 支持消息可靠&#xff0c;消息防重&#xff0c;消息有序。同时基础架构有分布式权限&…

深入教程:在STM32上实现能源管理系统

引言 能源管理系统&#xff08;EMS&#xff09;在提高能源效率、减少能源消耗和支持可持续发展方面起着关键作用。本教程将介绍如何在STM32微控制器上开发一个能源管理系统&#xff0c;这种系统能够监控和控制能源使用&#xff0c;适用于家庭自动化、工业控制系统以及任何需要…

jQuery Moblie 笔记14 开发跨平台移动设备网页

相关内容&#xff1a;jQuery Moblie基础、操作、移动设备仿真器、jQuery Moblie网页实例、jQuery Moblie的UI组件、…… jQuery推出了一套新的函数库jQuery Mobile&#xff0c;目的是希望能够统一当前移动设备的用户界面(UI)。 移动设备开发应用程序目前大致分为两种&#xff…

MLP手写数字识别(3)-使用tf.data.Dataset模块制作模型输入(tensorflow)

1、tensorflow版本查看 import tensorflow as tfprint(Tensorflow Version:{}.format(tf.__version__)) print(tf.config.list_physical_devices())2、MNIST数据集下载与预处理 (train_images,train_labels),(test_images,test_labels) tf.keras.datasets.mnist.load_data()…

强大而简洁:初学Python必须掌握的14个单行代码

Python的魅力与单行代码的重要性 Python&#xff0c;作为一种高级编程语言&#xff0c;自诞生以来就以其简洁、易读、易学的特性而广受开发者喜爱。其魅力不仅在于其强大的功能和广泛的应用领域&#xff0c;更在于其能够用简洁的代码实现复杂的功能&#xff0c;这种能力在很大…

Redisson 分布式锁和同步器

系列文章目录 文章目录 系列文章目录前言前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 redisson 是基于redis的扩展库,使得redis除了应用于缓存以外,还能做队列…

FloodFill-----洪水灌溉算法(DFS例题详解)

目录 一.图像渲染&#xff1a; 代码详解&#xff1a; 二.岛屿数量&#xff1a; 代码详解&#xff1a; 三.岛屿的最大面积&#xff1a; 代码详解&#xff1a; 四.被围绕的区域&#xff1a; 代码详解&#xff1a; 五.太平洋大西洋水流问题&#xff1a; 代码详解&#x…

嵌入式单片机中必会的50个电路分享

单片机 电源 声音模块 收音机 485

操作系统-进程管理

1.进程的定义 2.进程的组成 3.进程的特点 4.进程控制结构 5.进程状态 6.进程挂起 6.线程优缺点 7.线程进程的比较 8 .为什么要使用线程 9.用户线程 9.内核线程 10.进程上下文切换信息储存在PCB中 11.fork()

JavaEE初阶Day 15:文件IO(1)

目录 Day 15&#xff1a;文件IO&#xff08;1&#xff09;IO文件1. 路径2. 文件的分类3. 使用Java针对文件系统进行操作3.1 属性3.2 构造方法3.3 方法 Day 15&#xff1a;文件IO&#xff08;1&#xff09; IO I&#xff1a;Input输入 O&#xff1a;Output输出 输入输出规则…

【python的魅力】:教你如何用几行代码实现文本语音识别

文章目录 引言一、运行效果二、文本转换为语音2.1 使用pyttsx32.2 使用SAPI实现文本转换语音2.3 使用 SpeechLib实现文本转换语音 三、语音转换为文本3.1 使用 PocketSphinx实现语音转换文本 引言 语音识别技术&#xff0c;也被称为自动语音识别&#xff0c;目标是以电脑自动将…

Tomcat启动闪退怎么解决(文末附终极解决方案)

AI是这么告诉我的 Tomcat启动时出现闪退问题可能由多种原因引起&#xff0c;以下是解决此类问题的一些通用方法&#xff1a; 检查环境变量&#xff1a; 确保已经正确设置了JAVA_HOME和JRE_HOME环境变量&#xff0c;并指向正确的Java安装路径。将Java的bin目录添加到系统的PATH…

c语言题目

一些关于c语言的题目 文章目录 一、计算程序输出二、以下程序运行时&#xff0c;若输入1abcedf2df<回车>输出结果是将flag的第二个bit置0结构体大小下列C程序执行后c输出结果为&#xff08;&#xff09;设有定义char *p[]{"Shanghai","Beijing",&quo…

scikit-learn:Python中的机器学习-1

简介&#xff1a;问题设置 什么是机器学习&#xff1f; 机器学习是关于构建具有可调参数的程序&#xff0c;这些参数可以自动调整&#xff0c;以便通过适应先前看到的数据来改善其行为。机器学习可以被认为是人工智能的一个子领域&#xff0c;因为这些算法可以被视为构建模块…