- 此分页组件已发布至NPM,欢迎下载并提意见
经过前面的几篇文章,我们已经完成了具有基本功能分页组件。当然这是从UI上来说的,对于分页组件来说,其更重要的使命是和后端进行交互,请求数据。
本文将对此进行一个简单的实现,内容不多,几分钟即可读完。
回调函数
在 config 中再定义一个 paging 方法,表示分页后的回调函数。异步请求便在此函数中进行。
调用分页组件:
...
render(){
return(
<article className = { style.main }>
<Pagination config = {{
pageCurr:1,
totalPage:21,
paging(obj){
console.log(obj)
}
}}></Pagination>
</article>
);
}
...
分页完成后调用属性中的 paging 回调函数,并将当前页(pageCurr)和每页显示的条数(pageCount)转给回调函数,回调函数拿到这两个属性就可以向后端请求数据了。
修改组件中的 go 方法:
...
// 更新 state
go(pageCurr,reset = false){
const {
groupCount
} = this.state;
const {
totalPage,
paging
} = this.props.config
this.setState({
pageCurr
});
// 处理上一页的情况
if(pageCurr % groupCount === 1){
this.setState({
startPage:pageCurr
})
}
// 处理下一页的情况
if(pageCurr % groupCount === 0){
this.setState({
startPage:pageCurr - groupCount + 1
})
}
// 如果点击最后两位的时候
if(totalPage - pageCurr < 2){
this.setState({
startPage:totalPage - groupCount,
})
}
// 选择每页条数后重新分页
if(reset === true){
this.setState({
pageCurr:1,
startPage:1,
});
}
setTimeout(()=>{
paging({
pageCurr:this.state.pageCurr,
pageCount:this.state.pageCount
})
});
}
...
我们看一下调用结果:
一切OK。
源码
下面给出该分页组件的源码(渲染 App 组件和 App 组件的样式 style.scss 未给出):
App.js(调用分页组件):
import React,{ Component } from "react";
import style from "./style.scss";
import Pagination from "./Pagination";
import fetch from "isomorphic-fetch";
export default class App extends Component{
constructor(props) {
super(props);
this.state = {
renderPage:false
};
}
async componentDidMount() {
await setTimeout(()=>{
new Promise((res)=>{
this.setState({
renderPage:true
})
})
},500)
}
render(){
return(
<article className = { style.main }>
<Pagination config = {{
pageCurr:1,
totalPage:21,
async paging(obj){
let data = await fetch("http://www.baidu.com").then((res)=>res.json());
console.log(data)
}
}}></Pagination>
</article>
);
}
}
Pagination.js(分页组件):
import React,{ Component } from "react";
import style from "./pagination.scss";
export default class Pagination extends Component{
constructor(props){
super(props)
// 设置当前页码,默认为第一页
this.state = {
pageCurr:1,
groupCount:7,
startPage:1,
pageCount:10,
}
}
componentDidMount() {
this.setState({
pageCountEle:document.querySelector("#pageCount"),
});
setTimeout(()=>{
document.addEventListener("click",(e)=>{
if(e.target.id !== "pageCount"){
this.state.pageCountEle.parentNode.className = style.hide;
}
},false);
},0)
}
create(){
const {
totalPage,
} = this.props.config;
const {
pageCurr,
groupCount,
startPage
} = this.state;
let pages = [];
if( totalPage <= 10){
pages.push(<li onClick = { this.goPrev.bind(this) } className = { this.state.pageCurr === 1? style.nomore:"" } key={0}>上一页</li>)
for(let i = 1;i <= totalPage; i++){
// 点击页码时调用 go 方法,根据 state 判断是否应用 active 样式
pages.push(<li onClick = { this.go.bind(this,i) } className = { pageCurr === i ? style.active : "" } key={i}>{i}</li>)
}
pages.push(<li onClick = { this.goNext.bind(this) } className = { this.state.pageCurr === totalPage? style.nomore:"" } key={totalPage + 1}>下一页</li>)
}else{
pages.push(<li className = { this.state.pageCurr === 1? style.nomore:"" } key={ 0 } onClick = { this.goPrev.bind(this) }>上一页</li>)
for(let i = startPage;i < groupCount + startPage;i ++){
if(i <= totalPage - 2){
pages.push(<li className = { this.state.pageCurr === i? style.active:""} key={i} onClick = { this.go.bind(this,i) }>{i}</li>)
}
}
// 分页中间的省略号
if(totalPage - startPage >= 9){
pages.push(<li className = { style.ellipsis } key={ -1 }>···</li>)
}
// 倒数第一、第二页
pages.push(<li className = { this.state.pageCurr === totalPage -1 ? style.active:""} key={ totalPage - 1 } onClick = { this.go.bind(this,totalPage - 1) }>{ totalPage -1 }</li>)
pages.push(<li className = { this.state.pageCurr === totalPage ? style.active:""} key={ totalPage } onClick = { this.go.bind(this,totalPage) }>{ totalPage }</li>)
// 下一页
pages.push(<li className = { this.state.pageCurr === totalPage ? style.nomore:"" } key={ totalPage + 1 } onClick = { this.goNext.bind(this) }>下一页</li>)
}
return pages;
}
// 更新 state
go(pageCurr,reset = false){
const {
groupCount
} = this.state;
const {
totalPage,
paging
} = this.props.config
this.setState({
pageCurr
});
// 处理下一页的情况
if(pageCurr % groupCount === 1){
this.setState({
startPage:pageCurr
})
}
// 处理上一页的情况
if(pageCurr % groupCount === 0){
this.setState({
startPage:pageCurr - groupCount + 1
})
}
// 点击最后两页的情况
if(totalPage - pageCurr < 2){
this.setState({
startPage:totalPage - groupCount,
})
}
// 选择每页条数后重新分页
if(reset === true){
this.setState({
pageCurr:1,
startPage:1,
});
}
setTimeout(()=>{
paging({
pageCurr:this.state.pageCurr,
pageCount:this.state.pageCount
})
});
}
// 页面向前
goPrev(){
let {
pageCurr,
} = this.state;
if(--pageCurr === 0){
return;
}
this.go(pageCurr)
}
// 页面向后
goNext(){
let {
pageCurr,
groupCount
} = this.state;
const {
totalPage,
} = this.props.config;
if(++pageCurr > totalPage){
return;
}
this.go(pageCurr)
}
// 选择每页条数
choosePageCount(e){
const {
pading
} = this.props.config;
const parentUI = this.state.pageCountEle.parentNode;
parentUI.className = (parentUI.className === style.hide)?"":style.hide;
}
confirmPageCount(pageCount){
const {
pageCountEle,
pageCurr,
} = this.state;
// 设置每页显示条数
this.setState({
pageCount
});
pageCountEle.innerHTML = pageCount;
pageCountEle.parentNode.className = style.hide;
setTimeout(()=>{
this.go(pageCurr, true);
},0);
}
render(){
const Pages = this.create.bind(this)();
return(
<div className = { style.main }>
<div className = { style.bar }>
<span>每页显示</span>
<div className = { style.select }>
<ul className = { style.hide }>
<li id="pageCount" onClick = { this.choosePageCount.bind(this) }>10</li>
<li onClick = { this.confirmPageCount.bind(this,10) }>10</li>
<li onClick = { this.confirmPageCount.bind(this,20) }>20</li>
<li onClick = { this.confirmPageCount.bind(this,30) }>30</li>
<li onClick = { this.confirmPageCount.bind(this,50) }>50</li>
</ul>
</div>
</div>
<ul className = { style.page }>
{ Pages }
</ul>
</div>
);
}
}
pagination.scss(分页组件样式):
.main{
display: flex;
width:100%;
justify-content:space-around;
align-items:flex-start;
}
.page{
list-style: none;
padding:0;
margin:0;
li{
float:left;
width:30px;
height:30px;
border:1px solid #e6e6e6;
text-align: center;
line-height: 30px;
color:#333;
cursor:pointer;
&:first-of-type,&:last-of-type{
width:auto;
padding:0 5px;
}
&:first-of-type{
margin-right:10px;
}
&:last-of-type{
margin-left:10px;
}
&::selection {
background-color: transparent;
}
}
}
.active{
color:#fff !important;
background: #54b0bd;
border-color:#54b0bd !important;
}
.nomore{
color:#b5b5b5 !important;
}
.ellipsis{
border:none !important;
margin:0 10px;
cursor: default !important;
}
// 下拉菜单
.bar{
display: flex;
justify-content:space-between;
align-items:flex-start;
color:#666;
span{
font-size: 12px;
}
}
.select{
width:48px;
height:calc(6 * 22px);
background: #fff;
margin-left:10px;
ul{
height:100%;
display: flex;
flex-direction:column;
justify-content:space-between;
list-style: none;
border:1px solid #e6e6e6;
padding:0;
margin:0;
li{
padding:3px 0;
padding-left:5px;
&:hover{
background: #54b0bd;
}
&:first-of-type{
border-bottom:1px solid #e6e6e6;
position: relative;
&::after{
content:"";
display: block;
width:7px;
height:25px;
background: url("./imgs/dropdown.png") no-repeat center center;
position: absolute;
top:0;
right:5px;
}
}
}
}
}
// 收起状态
ul.hide{
height:24px;
overflow: hidden;
li{
&:nth-of-type(n+2){
display: none;
}
}
}
完。
一步一步教你写 React 分页组件(一)
一步一步教你写 React 分页组件(二)
一步一步教你写 React 分页组件(三)
一步一步教你写 React 分页组件(四)
一步一步教你写 React 分页组件(五)
一步一步教你写 React 分页组件(六)