react 写 分页插件
其实分页插件无论在什么项目我们都会用到,现在的ui框架也自带这个插件,但我最近正在学习react,实在不知写什么。就用分页插件练一下手,如果有错误的请指出,谢谢。
思路
先总结一下思路吧,可能写博客,在写插件之间都应该总结一些思路吧。其实最难算的应该就是分页条数大于10的时候吧,有的用点代替,有的用轮播方式来代替,这里我使用点的方式来代替
公式: Math.ceil( total / pageSize ) 总条数除以一页多少条 得到总共多少页(这里使用的下取整,无论还余多少条,肯定会有新的一页。)
分页效果
参数
/**
* 分页插件
* @param total // 总条数
* @param page // 当前页
* @param pageSize // 一页多少条
* @param fastPage // 是否有上一页 或者 下一页
* @param onPageChange // 回调函数 页数改变时触发
* @param onPageSize // 回调函数,一页多少条时改变
* **/
复制代码
全部代码
import React from 'react';
import './pagination.less';
/**
* 分页插件
* @param total // 总条数
* @param page // 当前页
* @param pageSize // 一页多少条
* @param fastPage // 是否有上一页 或者 下一页
* @param onPageChange // 回调函数 页数改变时触发
* @param onPageSize // 回调函数,一页多少条时改变
* **/
class Pagination extends React.Component{
constructor(props){
super(props);
let params = {
total: 0, // 总条数
page: 1, // 当前页
pageSize: 10, // 一页多少条
pageSizeArray:[
{
title: '10/页',
key: 10,
},
{
title: '20/页',
key: 20,
},
{
title: '30/页',
key: 30,
},
{
title: '40/页',
key: 40,
},
{
title: '50/页',
key: 50,
},
],
totalArray: [],
activeIndex: 1,
fastPage: true, // 是否 上一页 和 下一页
defaultNum: 5,
pageNum: 0, //总共多少页
jumpValue:'',
}
this.state = Object.assign(params,this.props);
this.nextHandle = this.nextHandle.bind(this);
this.prevHandle = this.prevHandle.bind(this);
this.pageInit = this.pageInit.bind(this);
this.init = this.init.bind(this);
this.jumpLeave = this.jumpLeave.bind(this);
this.jumpChange = this.jumpChange.bind(this);
this.pageSizeHandle = this.pageSizeHandle.bind(this);
}
init(){ // 初始化整个函数
let pageNum = Math.ceil( this.state.total / this.state.pageSize );
return new Promise((resolve, reject) => {
this.setState({pageNum: pageNum},()=>{
resolve()
})
})
}
jumpLeave(e){
let _this = this;
if(e.keyCode == 13) {
if(this.state.jumpValue) {
let num = Number(this.state.jumpValue)
this.setState({activeIndex:num},()=>{
_this.pageInit();
})
}
}
}
pageInit(){
let pageNum = this.state.pageNum;
console.log(pageNum, 44444)
let totalArr = [];
/**
* 默认展示 5 条
* 1 ... 45678...10
* **/
let intervalNumber = this.state.defaultNum;
if(pageNum >= intervalNumber) {
let arr = [],arr1 = [],arr2 = [];
arr.push(1);
if(this.state.activeIndex > intervalNumber && this.state.activeIndex < pageNum - intervalNumber){ // 取中间部分
arr1.push('...');
arr1.push( this.state.activeIndex - 2 )
arr1.push( this.state.activeIndex - 1 )
arr1.push( this.state.activeIndex )
arr1.push( this.state.activeIndex + 1 )
arr1.push( this.state.activeIndex + 2 )
arr1.push('...');
} else if( this.state.activeIndex <= intervalNumber ) { // 取开头部分
for( let i =1; i< pageNum; i++ ) {
if(i == intervalNumber || i+1 == pageNum) {
break;
}
arr1.push(i+1);
}
if(pageNum > intervalNumber){
arr1.push('...')
}
} else if( this.state.activeIndex >= pageNum - intervalNumber ) { // 取末尾部分
arr1.push('...');
for( let i = pageNum - intervalNumber; i< pageNum; i++ ) {
if(i == pageNum) {
break;
}
arr1.push(i);
}
}
arr2.push(pageNum);
totalArr = totalArr.concat(arr,arr1,arr2)
} else {
for(let i=0; i<pageNum; i++) {
totalArr.push(i+1)
}
}
this.setState({totalArray:totalArr});
}
componentWillUpdate( prevState,state ){
// console.log(prevState,state, 9999)
}
componentWillMount(){ // 相当于mouted
this.init().then(() => {
this.pageInit()
});
}
componentWillReceiveProps(props){ // props 改变时 触发的函数
setTimeout(()=>{
this.state = Object.assign(this.state,this.props);
this.init().then(() => {
this.pageInit()
});
},0)
}
nextHandle(){
let _this = this;
if( this.state.activeIndex < this.state.pageNum ) {
let index = this.state.activeIndex + 1;
this.setState({activeIndex:index}, ()=>{
_this.props.onPageChang(index);
_this.pageInit();
})
}
}
prevHandle(){
let _this = this;
if( this.state.activeIndex > 1 ) {
let index = this.state.activeIndex - 1;
this.setState({activeIndex:index}, ()=>{
_this.props.onPageChang(index);
_this.pageInit();
})
}
}
jumpChange(e){
let val = e.target.value;
this.setState({'jumpValue':val});
}
itemClick(item,index){
let _this = this;
let num = this.state.activeIndex;
if( item == '...' && index > 2 ){
num += 5;
} else if(item == '...' && index < 5 ){
num -= 5;
}else{
num = item;
}
this.setState({activeIndex:num},()=>{
_this.pageInit()
_this.props.onPageChang(num);
})
}
pageSizeHandle(e){
let val = e.target.value;
let _this = this;
this.setState({pageSize:val},()=> {
_this.init().then(() => {
_this.pageInit()
});
_this.props.onPageSize(val);
})
}
render(){
const totalHtml = this.state.totalArray.map((item,index) => {
let activeClass= item == this.state.activeIndex ? 'text-active' : '';
return (
<span onClick={this.itemClick.bind(this,item,index)} key={index} className={`${activeClass}`}>
{item}
</span>
)
})
const pageSizeHtml = this.state.pageSizeArray.map((item, index) => {
return (
<option key={index} value={item.key}>{item.title}</option>
)
})
const nextPage = this.state.fastPage ? (<button disabled={this.state.activeIndex == this.state.pageNum} onClick={this.nextHandle} className={'next-page'}>下一页</button>) : '';
const prevPage = this.state.fastPage ? (<button disabled={this.state.activeIndex == 1} onClick={this.prevHandle} className={'prev-page'}>上一页</button>) : '';
return (
<div id={'pagination'}>
<div className={'page-content'}>
{prevPage}
<div className={'text-content'}>
{totalHtml}
</div>
{nextPage}
<div className="pageSize">
<select defaultValue={this.state.pageSize} onChange={this.pageSizeHandle}>
{pageSizeHtml}
</select>
</div>
<div className="jump">
<span>跳至</span>
<input value={this.jumpValue} onChange={this.jumpChange} onKeyUp={this.jumpLeave} />
<span>页</span>
</div>
<div className={'text-total'}>
总计:{this.state.total} 条
</div>
</div>
</div>
)
}
}
export default Pagination;复制代码
样式代码
#pagination{
.page-content {
display:flex;
.text-content {
span{
display:inline-block;
width: 28px;
line-height: 28px;
text-align: center;
.page();
border: 1px solid #ddd;
background-color:#efefef;
margin: 10px 6px;
color: #666;
}
.text-active{
.activePage();
}
}
.page(){
height: 28px;
border-radius: 4px;
&:hover{
cursor:pointer;
}
}
.activePage(){
border: 1px solid #1890ff;
background-color:#1890ff;
color: #fff;
}
.prev-page, .next-page{
.page();
.activePage();
margin: 10px 20px;
}
button[disabled], .next-page[disabled]{
border: 1px solid #ddd;
background-color:#efefef;
color: #999;
&:hover{
cursor:not-allowed;
}
}
.text-total{
height: 28px;
margin: 10px 20px;
line-height: 28px;
}
.jump{
margin: 10px 6px;
input{
width: 40px;
height: 28px;
border:1px solid #ddd;
border-radius: 4px;
margin: 0 6px;
padding: 0 6px;
&focus{
border:1px solid #1890ff;
}
}
}
.pageSize{
margin: 14px 6px;
select{
width: 100px;
}
}
}
}复制代码