一步一步教你写 React 分页组件(六)

  • 此分页组件已发布至NPM,欢迎下载并提意见

经过前面的几篇文章,我们已经完成了具有基本功能分页组件。当然这是从UI上来说的,对于分页组件来说,其更重要的使命是和后端进行交互,请求数据。
本文将对此进行一个简单的实现,内容不多,几分钟即可读完。

回调函数

在 config 中再定义一个 paging 方法,表示分页后的回调函数。异步请求便在此函数中进行。
调用分页组件:

...
render(){
    return(
        
); } ...

分页完成后调用属性中的 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
        })
    });
}
...

我们看一下调用结果:

一步一步教你写 React 分页组件(六)_第1张图片
回调函数.gif

一切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(
            
res.json()); console.log(data) } }}>
); } }

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(
  • 上一页
  • ) for(let i = 1;i <= totalPage; i++){ // 点击页码时调用 go 方法,根据 state 判断是否应用 active 样式 pages.push(
  • {i}
  • ) } pages.push(
  • 下一页
  • ) }else{ pages.push(
  • 上一页
  • ) for(let i = startPage;i < groupCount + startPage;i ++){ if(i <= totalPage - 2){ pages.push(
  • {i}
  • ) } } // 分页中间的省略号 if(totalPage - startPage >= 9){ pages.push(
  • ···
  • ) } // 倒数第一、第二页 pages.push(
  • { totalPage -1 }
  • ) pages.push(
  • { totalPage }
  • ) // 下一页 pages.push(
  • 下一页
  • ) } 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(
    每页显示
    • 10
    • 10
    • 20
    • 30
    • 50
      { Pages }
    ); } }

    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 分页组件(六)

    你可能感兴趣的:(一步一步教你写 React 分页组件(六))