项目需求背景介绍:
1.react+ant
2.由于列表数据过多,不希望显示所有分页(防止用户一上来就点击最后一页,数据量计算大请求缓慢)
3.期望的分页组件是少于十页正常显示,多余十页则只显示相邻的十个页码,类似于百度的分页效果,如图:


翻阅了很多ui库,都没有这样的分页组件,只能自己实现了
自定义实现:
自己加了首页和尾页的快速切换和页码快速跳转和总条数,根据需要可自行设置对应的参数true或false
/* eslint-disable */
// react通用分页组件(最多只显示10页)
import React,{memo, useState,useEffect} from 'react'
// 引用的图标
import {LeftOutlined, RightOutlined, DoubleLeftOutlined, DoubleRightOutlined} from '@ant-design/icons'
import './page.scss'
function CustomPage (props) {
// page当前页码,number
// size每页条数,number
// total数据总数,number
// changePage分页切换
// showJump是否显示快速跳转,true/false
// showTotal是否显示总数
// showEnds是否显示首页尾页快速切换
const { page=1, size=10, total=1, changePage, showJump=true, showTotal=true, showEnds=true} = props
const [pageArr, setPageArr] = useState([])//页面显示的页码数组
const [jumpPage, setJumpPage] = useState('')//快速跳转页码
// 初始化分页
function initializationPage () {
const totalPage = Math.ceil(total/size)//总页数
let result = [];//盛放当前显示的所有页码的数组
if(totalPage < 11){//总页数小于11页的情况
for(let i = 0;i<totalPage;i++){
result.push(i+1);
}
}else if(page > 5 && (totalPage - page) > 3){//当前页大于5且总页数减当前页大于3
result = [page-5,page-4,page-3,page-2,page-1,page,page+1,page+2,page+3,page+4]
}else if(page > 5 && totalPage - page < 4){//当前页大于5且总页数减当前页小于4
result = [totalPage-9,totalPage-8,totalPage-7,totalPage-6,totalPage-5,totalPage-4,totalPage-3,totalPage-2,totalPage-1,totalPage]
}else if(page<6 && totalPage > 9){//当前页小于6且总页数大于9
for(let i = 0;i<10;i++){
result.push(i+1);
}
}
setPageArr(result)
}
//快速跳转页码回车事件
function handleEnterKey (e) {
e.persist()
const value = e.target.value
if(e.nativeEvent.keyCode === 13){
if (value =='') {
return
}
changePage(parseInt(value))
setJumpPage('')
}
}
// 快速跳转框值发生变化
function changeJumpPage (e) {
e.persist()
const value = e.target.value
const totalPage = Math.ceil(total/size)
if (value != '') {
if (parseInt(value) > 0) {
// 如果输入的页码大于总页数,则默认最后一页
if (parseInt(value)>totalPage) {
setJumpPage(parseInt(totalPage))
} else {
setJumpPage(parseInt(value))
}
}
} else {
setJumpPage('')
}
}
useEffect(()=> {
initializationPage()
},[page,total,size])
return <div className='custom-page flex-start-center'>
{showTotal &&
<div className='total'>
<span>Total</span>
<span className='total-num'>{total}</span>
<span>items</span>
</div>
}
{showEnds &&
<div className={`first-page pre-page change-page ${page==1 ? 'click-none':''}`} onClick={()=>changePage(1)}><DoubleLeftOutlined/></div>
}
<div className={`pre-page change-page ${page==1 ? 'click-none':''}`} onClick={()=>changePage(page-1)}><LeftOutlined/></div>
<ul className='pagination-ul flex-start-center'>
{pageArr.map(i=> <li onClick={()=>changePage(i)} key={i} className={page==i ? 'selected-act' : ''}>{i}</li>)}
</ul>
<div className={`next-page change-page ${page==Math.ceil(total/size) ? 'click-none':''}`} onClick={()=>changePage(page+1)}><RightOutlined/></div>
{showEnds &&
<div className={`last-page pre-page change-page ${page==Math.ceil(total/size) ? 'click-none':''}`} onClick={()=>changePage(Math.ceil(total/size))}><DoubleRightOutlined/></div>
}
{showJump &&
<div className='jump-page'>
<span>go to</span>
<input type="number" value={jumpPage} onChange={changeJumpPage} onKeyPress={handleEnterKey} />
<span>page</span>
</div>
}
</div>
}
export default memo(CustomPage)
.custom-page {
width: fit-content;
.selected-act{
color: $main-color-drak-green;
border-color: $main-color-drak-green;
}
.change-page{
font-size: 16px;
color: #000;
height: 32px;
border: 1px solid #d9d9d9;
border-radius: 4px;
line-height: 32px;
min-width: 32px;
text-align: center;
cursor: pointer;
&:hover {
color: $main-color-drak-green;
border-color: $main-color-drak-green;
}
}
.click-none {
opacity: 0.3;
pointer-events: none;
}
.pre-page {
margin-right: 8px;
}
.last-page {
margin-left: 8px;
}
ul {
margin: 0;
}
li{
list-style: none;
height: 32px;
line-height: 32px;
min-width: 32px;
text-align: center;
margin-right: 8px;
border: 1px solid #d9d9d9;
border-radius: 4px;
outline: 0;
cursor: pointer;
&:hover {
color: $main-color-drak-green;
border-color: $main-color-drak-green;
}
}
.total {
margin-right: 15px;
.total-num {
margin: 0 8px;
}
}
.jump-page {
margin-left: 15px;
input {
-moz-appearance:textfield;
height: 32px;
width: 50px;
border: 1px solid #d9d9d9;
border-radius: 4px;
outline:none;
margin: 0 10px;
text-indent: 10px;
&:focus {
border-color: $main-color-drak-green;
}
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
appearance: none;
margin: 0;
}
input[type="number"] {
-moz-appearance: textfield;
}
}
}
//使用
//xxx为组件路径
import CustomPage from 'xxx'
function onChangePage (page) {
//写自己的分页切换逻辑
}
...
<CustomPage changePage={onChangePage} />
附上默认配置的效果图



网友评论