React JS中如何在antd Table组件内使用自定义分页功能
实现思路
- 关闭antd Table内置分页:将
pagination属性设为false,无需修改原有筛选、排序逻辑,Table的onChange事件仍会正常返回筛选、排序参数 - 独立维护分页状态:单独引入antd Pagination组件放在Table外部,自主控制分页逻辑、上下页按钮状态
- 批量拉取+前端分页:每次拉取50条数据追加到本地缓存,前端按每页10条切片渲染,根据本地已拉取数据量和后台总数据量判断是否还有未拉取数据,控制下一页按钮启用状态
完整示例代码
import { useState, useEffect } from 'react' import { Table, Pagination } from 'antd' // 模拟接口请求,实际替换为你的业务接口即可 const mockApi = (offset, limit) => { return new Promise(resolve => { setTimeout(() => { const total = 100 // 后台总数据量,实际由接口返回 const list = Array.from({ length: limit }, (_, i) => ({ id: offset + i + 1, name: `数据${offset + i + 1}` })).filter(item => item.id <= total) resolve({ data: { list, total } }) }, 500) }) } const CustomPaginationTable = () => { const [allFetchedData, setAllFetchedData] = useState([]) // 本地已拉取的全量数据 const [currentPage, setCurrentPage] = useState(1) const pageSize = 10 // 每页展示10条 const [totalBackend, setTotalBackend] = useState(0) // 后台总数据量 const [loading, setLoading] = useState(false) // 计算已拉取数据可支持的最大页数 const maxFetchedPage = Math.ceil(allFetchedData.length / pageSize) // 计算后台总数据对应的总页数 const totalPage = Math.ceil(totalBackend / pageSize) // 是否还有未拉取的后台数据 const hasMore = allFetchedData.length < totalBackend // 当前页要展示的10条数据 const currentPageData = allFetchedData.slice((currentPage - 1) * pageSize, currentPage * pageSize) // 拉取数据逻辑,每次拉取50条 const fetchBatchData = async () => { setLoading(true) const res = await mockApi(allFetchedData.length, 50) setAllFetchedData(prev => [...prev, ...res.data.list]) setTotalBackend(res.data.total) setLoading(false) } // 首次加载拉取第一批数据 useEffect(() => { fetchBatchData() }, []) // 分页切换逻辑 const handlePageChange = (page) => { // 要跳转的页数超过已拉取数据支持的最大页数,且还有未拉取数据时,触发新的拉取 if (page > maxFetchedPage && hasMore) { fetchBatchData().then(() => { setCurrentPage(page) }) return } setCurrentPage(page) } // 自定义分页项渲染,控制上下页按钮禁用状态 const paginationItemRender = (page, type, originalElement) => { if (type === 'next') { // 下一页禁用条件:已经到最后一页 或 没有更多未拉取数据且已经到已拉取数据的最后一页 const isNextDisabled = currentPage >= totalPage || (currentPage >= maxFetchedPage && !hasMore) return { ...originalElement, props: { ...originalElement.props, disabled: isNextDisabled } } } if (type === 'prev') { const isPrevDisabled = currentPage <= 1 return { ...originalElement, props: { ...originalElement.props, disabled: isPrevDisabled } } } return originalElement } // 表格列配置,可根据实际需求修改 const columns = [ { title: 'ID', dataIndex: 'id', key: 'id', sorter: (a,b) => a.id - b.id }, { title: '名称', dataIndex: 'name', key: 'name' } ] return ( <div> <Table columns={columns} dataSource={currentPageData} loading={loading} pagination={false} // 关闭内置分页 onChange={(pagination, filters, sorter) => { // 原有筛选、排序逻辑直接在这里处理即可,无需修改 console.log('筛选参数:', filters, '排序参数:', sorter) }} /> <div style={{ marginTop: 16, textAlign: 'right' }}> <Pagination current={currentPage} pageSize={pageSize} total={totalBackend} onChange={handlePageChange} itemRender={paginationItemRender} showTotal={total => `共 ${total} 条数据`} /> </div> </div> ) } export default CustomPaginationTable
关键说明
- 关闭内置分页后不会影响原有筛选、排序功能:Table的
onChange事件仍会正常返回filters(筛选参数)、sorter(排序参数),原有处理逻辑可以直接复用 - 上下页按钮控制:通过Pagination的
itemRender属性自定义按钮渲染,可自由控制禁用状态,不需要额外自定义整个分页组件,样式和antd原生保持一致 - 批量拉取逻辑:每次拉取50条追加到本地缓存,只有当用户翻到已拉取数据的最后一页且还有未拉取数据时,才会触发下一批数据拉取,符合需求中的next按钮交互逻辑
- 如果你需要完全自定义分页组件的UI,也可以不用antd的Pagination,自己写上下页按钮和页码展示,逻辑和上述示例完全一致
内容的提问来源于stack exchange,提问作者Mei Lie
相关产品推荐
相关产品推荐

