美文网首页React
一步一步教你写 React 分页组件(六)

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

作者: 柏丘君 | 来源:发表于2017-05-12 23:14 被阅读711次
    • 此分页组件已发布至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
            })
        });
    }
    ...
    

    我们看一下调用结果:

    回调函数.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(
                <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 分页组件(六)

    相关文章

      网友评论

      本文标题:一步一步教你写 React 分页组件(六)

      本文链接:https://www.haomeiwen.com/subject/iyltxxtx.html