React+TS前台项目实战(十六)-- 全局常用组件Pagination封装

文章目录

  • 前言
  • Pagination组件
    • 1. 功能分析
    • 2. 代码+详细注释
    • 3. 使用方式
    • 4. 效果展示 [PC端&手机端]
  • 总结


前言

在上篇文章中,我们封装了表格组件Table,本文则继续封装配套使用的分页器组件。想看Table表格组件的,可自行查看全局常用组件Table封装


Pagination组件

1. 功能分析

(1)渲染一个带有分页功能的用户界面,包括导航到第一页、上一页、下一页和最后一页的按钮,并实现响应式布局
(2)提供一个输入框,允许用户手动输入页码,并提供一个按钮用于跳转到指定页码
(3)通过调用onChange prop来更新页码,并根据当前页数更新UI显示
(4)通过自定义的useIsMobile hook来判断设备类型,根据设备类型显示不同效果
(5)使用国际化语言显示文案

2. 代码+详细注释

// @/components/Pagination/index.tsx
import { useState, FC } from 'react'
import { useTranslation } from 'react-i18next'
import { PaginationLeft, PaginationRight, PaginationContainer } from './styled'
import { useIsMobile } from '@/hooks'
import Button from '@/components/Button'
import LeftArrow from './left_arrow.png'
import RightArrow from './right_arrow.png'
import DisLeftArrow from './disabled_left_arrow.png'
import DisRightArrow from './disabled_right_arrow.png'// 组件的属性类型
type Props = {currentPage: number // 当前页码total: number // 总页数gotoPage?: number // 跳转页码,默认为当前页码加一onChange: (page: number, size?: number) => void // 页码改变时的回调函数className?: string // 组件额外的class名pageSize?: number // 每页显示条目数pageSizes?: number[] // 每页显示条目数的可选项
}/*** 分页组件* @param currentPage 当前页码* @param total 总页数* @param gotoPage 跳转页码,默认为当前页码加一* @param onChange 页码改变时的回调函数* @param className 组件额外的class名* @param pageSize 每页显示条目数* @param pageSizes 每页显示条目数的可选项*/
const Pagination: FC<Props> = ({currentPage,total,gotoPage = currentPage === total ? total : currentPage + 1,onChange,className,pageSize,pageSizes,
}) => {// 判断是否是移动端const isMobile = useIsMobile()// 获取i18n翻译函数const { t } = useTranslation()// 创建一个state,用于存储输入框的值const [inputVal, setInputVal] = useState(gotoPage)// 计算总页数,并确保总页数大于0const totalCount = Math.max(total, 1)// 计算当前页数,并确保当前页数在范围内const current = Math.min(Math.max(currentPage, 1), total)// 移动端中间描述文本const mobileMiddleDescrip = `${t('pagination.total_page')} ${totalCount} ${t('pagination.end_page')}`// PC端中间描述文本const pcMiddleDescrip = `${t('pagination.current_page')} ${current} ${t('pagination.of_page')} ${totalCount} ${t('pagination.end_page',)}`// 页码更新const changePage = (page: number) => {if (page && page >= 1 && page <= totalCount) {setInputVal(Math.min(page + 1, totalCount))onChange(page)}}return (<PaginationContainer className={className}><PaginationLeft isFirstPage={current === 1} isLastPage={current === totalCount}><Button className="first-button" onClick={() => changePage(1)}>{t('pagination.first')}</Button><Button className="left-button" onClick={() => changePage(current - 1)}><img src={current === 1 ? DisLeftArrow : LeftArrow} alt="左侧按钮" /></Button>{!isMobile && <span className="middle-discrip">{pcMiddleDescrip}</span>}<Button className="right-button" onClick={() => changePage(current + 1)}><img src={current === totalCount ? DisRightArrow : RightArrow} alt="右侧按钮" /></Button>{isMobile && <span className="middle-discrip">{mobileMiddleDescrip}</span>}<Button className="last-button" onClick={() => changePage(totalCount)}>{t('pagination.last')}</Button></PaginationLeft><PaginationRight><span className="page-label">{t('pagination.page')}</span><inputtype="text"className="page-input"pattern="[0-9]*"value={inputVal}onChange={event => {const pageNo = parseInt(event.target.value, 10)setInputVal(Number.isNaN(pageNo) ? 0 : Math.min(pageNo, totalCount))}}/><Button className="page-go-to" onClick={() => changePage(inputVal)}>{t('pagination.goto')}</Button></PaginationRight></PaginationContainer>)
}export default Pagination
--------------------------------------------------------------------------------------------------------------
// @/components/Pagination/styled.tsx
import styled from 'styled-components'
import variables from '../../styles/variables.module.scss'
export const PaginationContainer = styled.div`display: flex;flex-direction: row;padding: 10px 20px;background: #fff;
`
export const PaginationLeft = styled.div`display: flex;align-items: center;justify-content: center;flex: 3;font-size: 14px;@media (max-width: ${variables.mobileBreakPoint}) {padding-left: 0;justify-content: flex-start;}.first-button,.last-button {padding: 4px 8px;border-radius: 5px;background: #f5f5f5;cursor: pointer;color: ${({ isFirstPage }: { isFirstPage: boolean }) => (isFirstPage ? '#969696' : '#000000')};cursor: ${({ isFirstPage }: { isFirstPage: boolean }) => (isFirstPage ? 'pointer' : 'auto')};&:hover {background: #999;}@media (max-width: ${variables.mobileBreakPoint}) {display: none;}}.left-button,.right-button {margin-left: 20px;width: 30px;height: 30px;display: flex;align-items: center;justify-content: center;border-radius: 5px;background: #f5f5f5;cursor: ${({ isFirstPage }: { isFirstPage: boolean }) => (isFirstPage ? 'pointer' : 'auto')};&:hover {background: #999;}img {width: 8px;}@media (max-width: ${variables.mobileBreakPoint}) {margin-left: 5px;}}.right-button {cursor: ${({ isLastPage }: { isLastPage: boolean }) => (isLastPage ? 'pointer' : 'auto')};}.last-button {margin-left: 20px;color: ${({ isLastPage }: { isLastPage: boolean }) => (isLastPage ? '#969696' : '#000000')};cursor: ${(props: { isFirstPage: boolean; isLastPage: boolean }) => (props.isLastPage ? 'none' : 'auto')};}.middle-discrip {display: flex;align-items: center;justify-content: center;height: 30px;background: #f5f5f5;border-radius: 5px;font-size: 12px;padding: 0 12px;margin-left: 20px;white-space: nowrap;@media (max-width: ${variables.mobileBreakPoint}) {background: #fff;border-radius: 0;margin: 0 5px;padding: 0;}}
`export const PaginationRight = styled.div`display: flex;align-items: center;flex: 2;font-size: 14px;@media (max-width: ${variables.mobileBreakPoint}) {justify-content: flex-end;}.page-input {width: 120px;height: 30px;border-radius: 5px;background-color: rgb(245, 245, 245);color: rgb(204, 204, 204);margin-right: 40px;outline: none;border: none;padding-left: 10px;@media (max-width: ${variables.mobileBreakPoint}) {width: 60px;margin-right: 20px;font-size: 12px;}}.page-label {margin-right: 20px;@media (max-width: ${variables.mobileBreakPoint}) {display: none;}}.page-go-to {height: 30px;line-height: 30px;padding: 0 10px;background: #f5f5f5;border-radius: 6px;border: none;outline: none;cursor: pointer;&:hover {background: #999;}@media (max-width: ${variables.mobileBreakPoint}) {font-size: 12px;}}
`

3. 使用方式

// 引入组件
import Pagination from "@/components/Pagination";
// 使用
<PaginationcurrentPage={1}PageSize={10}PageSizes={[10, 20, 30]}total={data?.total ?? 1}onChange={handlePageChange}
/>
const handlePageChange = (page: number) => {console.log('handlePageChange', page)
}

4. 效果展示 [PC端&手机端]

(1)PC端
在这里插入图片描述
(2)手机端
在这里插入图片描述


总结

下一篇讲【开始首页编码教学】。关注本栏目,将实时更新。

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

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

相关文章

QuantML-Qlib Model | Kansformer: KAN+Transformer时序模型用于股票收益率预测

QuantML-Qlib Model | Kansformer&#xff1a; KANTransformer时序模型用于股票收益率预测 原创 QuantML QuantML 2024-06-18 20:57 上海 Content 之前公众号介绍了几篇KAN的文章&#xff0c;也做过KAN相关的模型&#xff1a; What KAN I say&#xff1f;KAN代码全解析 Qu…

胖东来启示录:传统商超如何逆境求生?

近日&#xff0c;经过胖东来精心调改的永辉超市郑州信万广场店盛大开业&#xff0c;首日销售额高达188万元&#xff0c;客流量突破1.2万人&#xff0c;业绩飙升13.9倍&#xff0c;这一惊人数据无疑为当前低迷的传统商超行业带来了一线生机。胖东来&#xff0c;这位零售业的黑马…

java—类反射机制

简述 反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息&#xff08;如成员变量&#xff0c;构造器&#xff0c;成员方法等&#xff09;&#xff0c;并能操作对象的属性及方法。反射机制在设计模式和框架底层都能用到。 类一旦加载&#xff0c;在堆中会产生…

Java程序之让气球上升

问题&#xff1a; ACM比赛时间再次举行&#xff01;看到气球四处漂浮是多么的兴奋啊。但要告诉你一个秘密&#xff0c;评委们最喜欢的时间是猜测最流行的问题。比赛结束后&#xff0c;他们会数出每种颜色的气球&#xff0c;然后找到结果。今年&#xff0c;他们决定把这份可爱的…

【建设方案】基于gis地理信息的智慧巡检解决方案(源文件word)

传统的巡检采取人工记录的方式&#xff0c;该工作模式在生产中存在很大弊端&#xff0c;可能造成巡检不到位、操作失误、观察不仔细、历史问题难以追溯等现象&#xff0c;使得巡检数据不准确&#xff0c;设备故障隐患得不到及时发现和处理。因此建立一套完善的巡检管理系统是企…

Java程序之寻找自幂数

题目&#xff1a; 自幂数是指一个 n 位数&#xff08;3≤n≤7 &#xff09;&#xff0c;它的每个位上的数字的 n 次幂之和等于它本身&#xff08;例如&#xff1a;1^3 5^3 3^3 153&#xff1b;1^46^43^44^41634&#xff09;。三位自幂数&#xff1a;水仙花数&#xff1b;四位…

HeidiSQL导入与导出数据

HeidiSQL两种导入与导出数据的方法&#xff1a;整个库复制&#xff0c;和仅复制数据 一 整个库复制 1 选中需要导出的数据库(这里是MyDBdata)&#xff0c;点击导出为SQL脚本。 2 按照如图进行选择 3 选做&#xff1a;删除当前数据库【如果有】 -- 删除数据库 USE mysql; D…

python-题库篇-Python语言特性

文章目录 Python语言特性1 Python的函数参数传递2 Python中的元类(metaclass)3 staticmethod和classmethod4 类变量和实例变量5 Python自省6 字典推导式7 Python中单下划线和双下划线8 字符串格式化:%和.format9 迭代器和生成器10 *args and **kwargs11 面向切面编程AOP和装饰器…

基于SpringBoot+大数据城市景观画像可视化设计和实现

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

C语言入门系列:初识函数

文章目录 一&#xff0c;C语言函数与数学函数的区别1&#xff0c;回忆杀-初中数学2&#xff0c;C语言中的函数 二&#xff0c; 函数的声明1&#xff0c;函数头1.1&#xff0c;函数名称1.2&#xff0c;返回值类型1.3&#xff0c;参数列表 2&#xff0c;函数体2.1&#xff0c;函数…

Android使用zxing生成二维码

效果图如下&#xff1a; **前提&#xff1a;导入zxing的jar后开始操作&#xff0c;老规矩最后有源码&#xff0c;作者布局默认相对布局。 第一步&#xff1a;定义二维码的长宽高及图片控件** 第二步&#xff1a;实例化QRCodeWriter后利用for循环将二维码画出来&#xff0c;然后…

用Visual Studio调试CMake项目并生成Visual Studio工程

一. 在Windows系统上安装CMake 访问CMake官方网站https://cmake.org/download&#xff0c;或通过文末链接下载&#xff1a;在下载页面上&#xff0c;找到并点击“Download”链接以获取最新的稳定版本的CMake。请注意&#xff0c;虽然新版本可能包含更多功能和改进&#xff0c;…

关于DrawTools的分析- 一个优秀的C#开源绘图软件

国外大佬&#xff0c;曾经写过两个关于DrawTools相关的开源绘图软件。 我更新了一个优化的版本如下图&#xff0c;稍后会发布更新给大家。 需要的用户可发邮件给我 448283544qq.com 应用于AGV地图编辑器如下&#xff1a; 那么这个优于很多普通的画布软件&#xff0c;包含点、…

qt 简单实验 读取json格式的配置文件

1.概要 2.代码 //#include "mainwindow.h"#include <QApplication> #include <QFile> #include <QJsonDocument> #include <QJsonObject> #include <QDebug> //读取json数据的配置文件QJsonObject readJsonConfigFile(const QString …

iptables动作总结

ACCEPT动作 将数据包放行&#xff0c;进行完此处理动作后&#xff0c;将不再比对当前链的其它规则&#xff0c;直接跳往下一个规则链。 范例如下&#xff1a; #新增自定义链TEST_ACCEPTiptables -t filter -N TEST_ACCEPT#新增自定义链TEST_ACCEPT2iptables -t filter -N TES…

0基础学习线段树

前言&#xff1a; 线段树&#xff1a;用树来表示一个一个的线段区间。 1、为什么要使用线段树&#xff1f; 题目&#xff1a;给定一个数组nums&#xff0c;我们有两种下面两种操作 1、查询nums数组下标i到下标j的和&#xff1b; 2、将nums数组指定下标的值改为指定的一个新…

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-28批量规范化

28批量规范化 """可持续加速深层网络的收敛速度""" import torch from torch import nn import liliPytorch as lp import matplotlib.pyplot as pltdef batch_norm(X, gamma, beta, moving_mean, moving_var, eps, momentum):""&quo…

Swift 中的动态数组

Swift 的 Array 类型是一种强大而灵活的集合类型&#xff0c;可以根据需要自动扩展或缩减其容量。 动态数组的基本概念 Swift 中的数组是基于动态数组&#xff08;dynamic array&#xff09;的概念实现的。动态数组能够根据需要自动调整其容量&#xff0c;以容纳新增的元素&a…

Benchmarking Panoptic Scene Graph Generation (PSG), ECCV‘22 场景图生成,利用PSG数据集

2080-ti显卡复现 源代码地址 Jingkang50/OpenPSG: Benchmarking Panoptic Scene Graph Generation (PSG), ECCV22 (github.com) 安装 pytorch 1.7版本 cuda10.1 按照readme的做法安装 我安装的过程如下图所示,这个截图是到了pip install openmim这一步 下一步 下一步 这一步…

C语言 | Leetcode C语言题解之第167题两数之和II-输入有序数组

题目&#xff1a; 题解&#xff1a; int* twoSum(int* numbers, int numbersSize, int target, int* returnSize) {int* ret (int*)malloc(sizeof(int) * 2);*returnSize 2;int low 0, high numbersSize - 1;while (low < high) {int sum numbers[low] numbers[high]…