【前端项目——分页器】手写分页器实现(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.rhkb.cn/news/319115.html

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

相关文章

如何免费体验 gpt2-chatbot

如何免费体验 gpt2-chatbot 就在五一假期期间&#xff0c;一个神秘模型在没有任何官方文件的情况下突然发布。发布后不到 12 小时就立即引起人工智能爱好者和专家们的关注。这个名为“gpt2-chatbot”的神秘新模型凭借其令人印象深刻的能力轰动全球。有人猜测它可能是 OpenAI 的…

Docker Compose如何安装

Docker Compose的安装通常依赖于你的操作系统。以下是在不同操作系统中安装Docker Compose的方法&#xff1a; Linux 系统 //下载最新版本的Docker Compose sudo curl -L "https://github.com/docker/compose/releases/download/v2.5.1/docker-compose-$(uname -s)-$(un…

SQL如何利用Bitmap思想优化array_contains()函数

目录 0 问题描述 1 位图思想 2 案例实战 3 小结 0 问题描述 在工作中&#xff0c;我们往往使用array_contains()函数来进行存在性问题分析&#xff0c;如判断某个数是否在某个数组中&#xff0c;但是当表数据量过多&#xff0c;存在大量array_contains()函数时&#xff0c;…

C语言:数据结构(双向链表)

目录 1、双向链表的结构2、顺序表和双向链表的优缺点分析3、双向链表的实现 1、双向链表的结构 注意&#xff1a;这⾥的“带头“跟前面我们说的“头节点”是两个概念&#xff0c;实际前面的在单链表阶段称呼不严谨&#xff0c;但是为了更好的理解就直接称为单链表的头节点。 带…

网络聊天室:通过Servlet和JSP,结合session和application实现(文末附源码)

目录 一.成品效果 二.代码部分 chat.jsp ChatServlet 一.成品效果 在启动成功后&#xff0c;我们就可以在任意俩个浏览器页面中相互发消息&#xff0c;如图所示左边屏幕使用的是Edge浏览器&#xff0c;右图使用的是火狐浏览器。当然笔者这里只是简单实现最基本的一些功能&…

从键入网址到网页显示,期间发生了什么?

从键入网址到网页显示&#xff0c;期间发生了什么&#xff1f; 孤单小弟【HTTP】真实地址查询【DNS】指南帮手【协议栈】可靠传输【TCP】远程定位【IP】两点传输【MAC】出口【网卡】送别者【交换机】出境大门【路由器】互相扒皮【服务器与客户端】相关问答 不少小伙伴在面试过程…

RabbitMq基础概念知识复习

消息拥有消息头和消息体&#xff0c;消息具有rounting key&#xff0c;主题交换机和扇形交换机都是发布与订阅的实现方式&#xff0c;主题交换机用于匹配接收的消息的rount key 动态匹配模式匹配到多个符合的队列&#xff0c;扇形fanout交换机则不会使用消息的路由key&#xff…

SQLite如何处理CSV 虚拟表(三十七)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite的DBSTAT 虚拟表&#xff08;三十六&#xff09; 下一篇:SQLite的扩展函数Carray()表值函数(三十八) ​ RFC4180格式是一种文本文件格式&#xff0c;被用于表格数据间的交互&#xff0c;也可将表格数据转化…

【机器学习】集成方法---Boosting之AdaBoost

一、Boosting的介绍 1.1 集成学习的概念 1.1.1集成学习的定义 集成学习是一种通过组合多个学习器来完成学习任务的机器学习方法。它通过将多个单一模型&#xff08;也称为“基学习器”或“弱学习器”&#xff09;的输出结果进行集成&#xff0c;以获得比单一模型更好的泛化性…

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

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

图床搭建GitHub+PicGo+jsdelivr(CDN)+Typora(内附加速工具)

目录 安装PicGo GitHub配置与加速器 配置PicGo 使用typroa 安装PicGo PicGo是一个用于上传图片的客户端&#xff0c;支持拖拽上传、剪贴板上传&#xff0c;功能十分方便。 下载地址&#xff1a; https://github.com/Molunerfinn/PicGo/releases 个人网盘自取版本2.4.0…

nginx变量自定义日志收集

内置变量 $remote_addr&#xff1b;存放了客户端的地址&#xff0c;注意是客户端的公网IP&#xff0c;也就是一家人访问一个网站&#xff0c;则会显示为路由器的公网IP。 $args&#xff1b;变量中存放了URL中的指令 [rootlocalhost conf.d]# cat pc.conf server {listen 80;se…

【UnityRPG游戏制作】RPG项目的背包系统商城系统和BOSS大界面

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

用于复杂任务的 AI 编码引擎:多文件多步骤拆解实现 | 开源日报 No.239

plandex-ai/plandex Stars: 3.1k License: AGPL-3.0 plandex 是一个用于复杂任务的 AI 编码引擎。 使用长时间运行的代理完成跨多个文件且需要多个步骤的任务将大型任务分解为较小子任务&#xff0c;逐一实现&#xff0c;直至完成整个工作帮助处理积压工作、使用陌生技术、摆…

Gateway结合Nacos使用!!!

一、本地结合使用 1. 引入依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> 2. bootstarp.yml配置文件 如果Nacos中配置使用yaml格式&…

【牛客网】值周

原题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 差分。 因为l<100000000,所以数组开1e8。 唯一需要注意的点就是前面给b[0]单独赋值为1&#xff08;因为如果在循环中给b[0]赋值&…

利用大模型提升个性化推荐的异构知识融合方法

在推荐系统中&#xff0c;分析和挖掘用户行为是至关重要的&#xff0c;尤其是在美团外卖这样的平台上&#xff0c;用户行为表现出多样性&#xff0c;包括不同的行为主体&#xff08;如商家和产品&#xff09;、内容&#xff08;如曝光、点击和订单&#xff09;和场景&#xff0…

iOS 实现类似抖音翻页滚动效果

这里是效果图 参考抖音的滚动效果&#xff0c;需要我们在结束拖动的时候&#xff0c;动画设置偏移量 这里有一个注意点&#xff0c;由于我们是在拖动结束的时候&#xff0c;手动改变tableview的偏移量&#xff0c; 改变了tableView 自身原有的的滚动效果&#xff0c;所以我们…

uniapp乡村社区户籍问外来人员管理系统 微信小程序python+java+node.js+php

基于微信小程序的外来人员管理系统项目的概述设计分析&#xff0c;主要内容有的私教预约平台系统平台的具体分析&#xff0c;进行数据库的是设计&#xff0c;数据采用MySQL数据库&#xff0c;并且对于系统的设计采用比较人性化的操作设计&#xff0c;对于系统出现的错误信息可以…

【 书生·浦语大模型实战营】作业(六):Lagent AgentLego 智能体应用搭建

【 书生浦语大模型实战营】作业&#xff08;六&#xff09;&#xff1a;Lagent & AgentLego 智能体应用搭建 &#x1f389;AI学习星球推荐&#xff1a; GoAI的学习社区 知识星球是一个致力于提供《机器学习 | 深度学习 | CV | NLP | 大模型 | 多模态 | AIGC 》各个最新AI方…