动手打造antd组件之pagination

本文正在参加「金石计划」

一:引言

本篇文章仿写antd组件库的pagination组件,也就是我们常用的分页组件。文章重点是模拟pagination组件的内部功能实现。

二:组件分析

观察下图,我们设计一个可配置的分页组件,其配置项包含如下

动手打造antd组件之pagination

  • className 类名
  • total 总数量
  • pageSize 一页的容量
  • pageNumber 页码
  • leftText 左分页控制组件
  • rightText 右分页控制组件
  • showQuickJumper 是否支持快速跳转
  • onChange 分页时触发回调函数

三:问题拆解

在设计组件前,我们可以先考子问题,最后组装起来就实现了目标组件。

问题1:分页左右切换如何控制?

  • 首先我们需要为分页组件传递一个total总数,分页组件根据总数/页容量自动计算展示的分页盒子数,通过我们只需通过index标记当前展示的页码,当点击左右分页时更新index就可。注意左右切换边界条件。

问题2:分页的快速跳转如何实现?

分页的快速跳转十分容易,只需要监听输入框输入的数字,然后更新index页码即可。

问题3:分页过多时,省略号逻辑如何处理?(重难点,比较复杂)

这个问题是分页组件的难点,难点,我也是在andt官网不停的切换才总结出对应规律,其规则主要是

  1. 页码总数<=7时全部展示

  2. 否则执行

    • 当前页码<=4时,展示前6个+省略+最后一个
    • 当前页码>=5 且 <= 总页码-4时,展示第1个+省略+当前页码为中心的5个+省略+最后一个
    • 当前页码> 总页码-4时,展示第1个+省略+后6个

五:pagination代码实现

总体代码除了分页过多有省略号时逻辑比较复杂,其余逻辑都十分简单。

import React, { useEffect, useState } from "react";
interface PaginationProps {
pageSize?:number
pageNumber?:number
total?:number,
leftText?:string,
rightText?:string
showQuickJumper?:boolean
onChange?:(e:number)=>void
}
const Pagination = (props:PaginationProps={pageSize:10,pageNumber:1,total:0}) => {
const {pageSize,pageNumber,total,onChange,showQuickJumper,leftText,rightText} = props;
const [paginationPageSize,setPaginationPageSize] = useState(pageSize);//页面容量
const [paginationPageNumber,setPaginationPageNumber] = useState(pageNumber);//页面当前编号
const [paginationTotal,setPaginationTotal] = useState(total);//总数量
const [totalPageSize,setTotalPageSize] = useState(0);//总页码
useEffect(()=>{
setTotalPageSize(Math.ceil(paginationTotal!/paginationPageSize!));
},[])//paginationPageNumber
const initPage = () => {
if(totalPageSize<=7) {
return (
Array(totalPageSize).fill(1).map((item,index)=>(
<div 
className={paginationPageNumber===(index+1)?"pagination_item pagination_item_actived":"pagination_item"} 
key={index+Math.random()}
>
{index+1}
</div>
))
)
}
if(paginationPageNumber!<=4) {
//前6个+省略+最后一个
return (
<>
{
Array(6).fill(1).map((item,index)=>(
<div 
className={paginationPageNumber===(index+1)?"pagination_item pagination_item_actived":"pagination_item"} 
key={index+Math.random()}
>
{index+1}
</div>
))
}
<div 
className='pagination_simple'
onClick={()=>{
if(paginationPageNumber!+5>=totalPageSize) {
setPaginationPageNumber(totalPageSize);
onChange&&onChange!(totalPageSize);
}else {
setPaginationPageNumber(paginationPageNumber!+5);
onChange&&onChange!(paginationPageNumber!+5);
}
}}
>
...
</div>
<div 
className={paginationPageNumber===(totalPageSize)?"pagination_item pagination_item_actived":"pagination_item"} 
key={paginationPageNumber!+Math.random()}
>
{totalPageSize}
</div>
</>
)
}
//第1个+省略+当前页码前后5个+省略+最后一个
if(paginationPageNumber!>=5 && paginationPageNumber!<=totalPageSize-4) {
return (
<>
<div
className={paginationPageNumber===(1)?"pagination_item pagination_item_actived":"pagination_item"} 
key={0+Math.random()}
>
1
</div>
<div 
className='pagination_simple'
onClick={()=>{
if(paginationPageNumber!-5<=1) {
setPaginationPageNumber(1);
onChange&&onChange!(1);
}else {
setPaginationPageNumber(paginationPageNumber!-5);
onChange&&onChange!(paginationPageNumber!-5);
}
}}
>
...
</div>
{
Array(5).fill(paginationPageNumber!-2).map((item,index)=>(
<div
className={paginationPageNumber===(item+index)?"pagination_item pagination_item_actived":"pagination_item"} 
key={item-Math.random()}
>
{item+index}
</div>
))
}
<div 
className='pagination_simple'
onClick={()=>{
if(paginationPageNumber!+5>=totalPageSize) {
setPaginationPageNumber(totalPageSize);
onChange&&onChange!(totalPageSize);
}else {
setPaginationPageNumber(paginationPageNumber!+5);
onChange&&onChange!(paginationPageNumber!+5);
}
}}
>
...
</div>
<div
className={paginationPageNumber===(totalPageSize)?"pagination_item pagination_item_actived":"pagination_item"} 
key={totalPageSize-Math.random()}
>
{totalPageSize}
</div>
</>
)
}
//展示第1个+省略+后6个
return (
<>
<div
className={paginationPageNumber===(1)?"pagination_item pagination_item_actived":"pagination_item"} 
key={0+Math.random()}
>
1
</div>
<div 
className='pagination_simple'
onClick={()=>{
if(paginationPageNumber!-5<=1) {
setPaginationPageNumber(1);
onChange&&onChange!(1);
}else {
setPaginationPageNumber(paginationPageNumber!-5);
onChange&&onChange!(paginationPageNumber!-5);
}
}}
>
...
</div>
{
Array(6).fill(totalPageSize-5).map((item,index)=>(
<div
className={paginationPageNumber===(item+index)?"pagination_item pagination_item_actived":"pagination_item"} 
key={item-Math.random()}
>
{item+index} 
</div>
))
}
</>
)
}
return (
<div className='pagination'>
<div 
onClick={()=>{
if(paginationPageNumber!==1)
{
setPaginationPageNumber(paginationPageNumber!-1);
onChange&&onChange!(paginationPageNumber!-1);
}   
}}
className={paginationPageNumber===1?"pagination_left pagination_left_disabled":"pagination_left"}
>
{leftText}
</div>
{
initPage()
}
<div
className={paginationPageNumber===Math.ceil(paginationTotal!/paginationPageSize!)?"pagination_right pagination_right_disabled":"pagination_right"}
onClick={()=>{
if(paginationPageNumber!==Math.ceil(paginationTotal!/paginationPageSize!)) {
setPaginationPageNumber(paginationPageNumber!+1);
onChange&&onChange!(paginationPageNumber!+1);
} 
}}
>
{rightText}
</div>
<div className="pagination_info">每页{paginationPageSize}条</div>
{
showQuickJumper && (
<div className="pagination_jump">
<span>跳至</span>
<input type="text" onKeyDown={(e)=>{
if(e.code==='Enter'){
//获取输入的数字进行跳转
if(Number(e.currentTarget?.value)>=1 && Number(e.currentTarget?.value)<=totalPageSize!) {
setPaginationPageNumber(Number(e.currentTarget?.value));
onChange && onChange(Number(e.currentTarget?.value))
}
}
}}/>
<span>页</span>
</div>
)
}
</div>
)
}
Pagination.defaultProps = {
pageNumber:1,
pageSize:10,
total:0,
showQuickJumper:false,
leftText:'<',
rightText:'>'
}
export default Pagination;

六:功能演示

演示1:默认

 <Pagination total={60}/>

动手打造antd组件之pagination

演示2:添加自动跳转

    <Pagination total={80} showQuickJumper/>

演示3:添加左右跳转配置

   <Pagination total={80} showQuickJumper leftText="左" rightText="右"/>

演示4:添加跳转回调函数

   <Pagination total={80} showQuickJumper onChange={(e)=>console.log(e)}/>

动手打造antd组件之pagination

演示5:分页数超过7时省略逻辑

<Pagination total={200}/>

动手打造antd组件之pagination

总结

今天pagination组件到此结束,希望大家多多支持,我们下一个组件见。

原文链接:https://juejin.cn/post/7212603037667819581 作者:前端兰博

(0)
上一篇 2023年3月21日 下午4:00
下一篇 2023年3月21日 下午4:11

相关推荐

发表回复

登录后才能评论