Table + Pagination 组件自定义表格分页

记录使用 Table + Pagination 组件分页时碰到的一些问题。

使用 Pagination 组件自定义分页

需求

使用 antdTable 组件的时候,我想自定义一个页脚,便于控制每页显示的条数。

以前也曾接触过表格展示数据。向后端发送的请求中,每条都要带上 page(页码) 和 size(每页大小) 参数,当时我没有考虑过为什么要这么做,直到今天,我突然明白,这是为了做分页。

向后端发送 pagesize 参数,是表明当前需要第 page 页的数据,每页有 size 条数据,便于后端返回相应数据。否则,如果后端返回全部数据,那么数据处理、筛选都要由前端来做。

引入组件

使用自定义 pagination 时要禁用表格自带的 pagination 属性。

<Table pagination={false} />

然后引入 Pagination 组件。

<Pagination />

必须的属性有如下几个。

  • total

    数据总条数

  • defaultPageSize | pageSize

    默认每页数据大小 | 每页数据大小

    按照实际需求,我们可以指定默认每页数据大小,也可以使用可变的 pageSize

  • current

    当前页码

  • onChange

    分页器发生变化时的回调
    类型:Function(current, size)

total 属性和 pageSize 用于计算当前需要分页总数,current 属性用于指定当前页码,onChange 属性用于当页码改变时,手动改变 state 中的当前页码。

具体见 antd-pagination

思路

  1. 我们使用 state 来保存当前页码,默认置为 1
  2. Pagination 组件根据 totalpageSize 计算出总页数
  3. 当我们手动点击切换页码时,会触发 onChange 回调函数,在 onChange 回调函数中设置 state 中保存的当前页码
  4. state 中的当前页码与 Pagination 组件的 current 属性绑定

代码

import React, { Component } from 'react';
import { Table, Button, Pagination } from 'antd';

const { Column } = Table;
const PageSize = 5;
const { log } = console;

export default class TableDemo extends Component {

    constructor(props) {
        super(props);
        this.setData = this.setData.bind(this);
        this.getData = this.getData.bind(this);
        this.changePage = this.changePage.bind(this);
        this.state = {
            current: 1,
            size: PageSize,
            total: 0
        }
    }

    // 生成数据
    setData(length) {
        const dataSource = [];
        for (let i = 0; i < length; i++) {
            dataSource.push({
                key: `${i}`,
                name: `tset ${i + 1}`,
                age: 32
            })
        }
        return {
            dataSource,
            total: length
        };
    }

    // 返回查询数据(页码, size)
    getData(page, size) {
        const { setData } = this;
        const data = setData(16);
        const result = [];
        const start = size * (page - 1);
        const end = size * page > data.dataSource.length ? data.dataSource.length : size * page;

        for (let i = start; i < end; i++) {
            result.push(data.dataSource[i]);
        }
        return {
            data: result,
            total: data.total
        };
    }

    // 页码改变时
    changePage(current, size) {
        this.setState({
            current
        })
    }

    render() {
        const { getData, changePage } = this;
        const { current: currentPage, size } = this.state;
        const dataSource = getData(currentPage, size);
        log('render')

        return (<div>
            <Table
                dataSource={dataSource.data}
                pagination={false}
            >
                <Column title="name" key='name' dataIndex='name' width={100} />
                <Column title="age" key='age' dataIndex='age' width={80} />
                <Column title="action" key='action' dataIndex='action' render={(tetx, record) => (
                    <Button href="javascript:;">update state</Button>
                )} />
            </Table>
            <Pagination
                total={dataSource.total}
                defaultPageSize={size}
                current={currentPage}
                onChange={changePage}
            />
        </div>)
    }
}