You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PrimeReact DataTable自定义分页器渲染问题求助

解决PrimeReact DataTable自定义分页器(带省略号样式)的问题

核心思路

要实现「1 2 3 ... 10」「1...8 9 10」「1 ..3 4 5..10」这类分页样式,需要手动计算页码显示逻辑,同时可靠获取总页数(兼容懒加载/非懒加载模式),避免直接依赖pageLinks导致的报错。

步骤1:正确获取总页数

不管是懒加载还是非懒加载,总页数都可以通过以下方式稳定获取:

  • 非懒加载模式:Math.ceil(data.length / rowsPerPage),其中data是你的数据源数组,rowsPerPage是每页条数
  • 懒加载模式:Math.ceil(totalRecords / rowsPerPage),totalRecords是后端返回的总条数

封装成工具函数:

const getTotalPages = () => {
  if (isLazy) {
    return Math.ceil(totalRecords / rowsPerPage);
  }
  return Math.ceil(data.length / rowsPerPage);
};

步骤2:生成带省略号的页码列表

根据当前页和总页数,生成符合需求的页码数组:

const generatePageNumbers = (currentPage, totalPages) => {
  const pages = [];
  // 总页数≤5时,直接显示所有页码
  if (totalPages <= 5) {
    for (let i = 1; i <= totalPages; i++) {
      pages.push(i);
    }
    return pages;
  }

  // 当前页在前3页:显示前3页 + 省略号 + 末页
  if (currentPage <= 3) {
    return [1, 2, 3, '...', totalPages];
  }

  // 当前页在后3页:显示首页 + 省略号 + 后3页
  if (currentPage >= totalPages - 2) {
    return [1, '...', totalPages - 2, totalPages - 1, totalPages];
  }

  // 中间页:显示首页 + 省略号 + 当前页前后各1页 + 省略号 + 末页
  return [1, '...', currentPage - 1, currentPage, currentPage + 1, '...', totalPages];
};

步骤3:自定义分页器模板与渲染

在DataTable中通过paginatorTemplate指定自定义模板,结合onPageChange更新页码列表:

完整组件示例

import { useState, useEffect } from 'react';
import { DataTable } from 'primereact/datatable';
import { Column } from 'primereact/column';
import { Button } from 'primereact/button';

const CustomPaginatorDataTable = ({ data, isLazy, totalRecords, rowsPerPage = 10 }) => {
  const [currentPage, setCurrentPage] = useState(1);
  const [pageNumbers, setPageNumbers] = useState([]);

  // 获取总页数
  const getTotalPages = () => {
    if (isLazy) {
      return Math.ceil(totalRecords / rowsPerPage);
    }
    return Math.ceil(data.length / rowsPerPage);
  };

  // 更新页码列表
  useEffect(() => {
    const totalPages = getTotalPages();
    setPageNumbers(generatePageNumbers(currentPage, totalPages));
  }, [currentPage, data.length, totalRecords, rowsPerPage]);

  // 处理页码点击
  const handlePageClick = (page) => {
    if (page === '...') return;
    setCurrentPage(page);
    // 懒加载模式下,这里需要调用后端接口获取对应页数据
  };

  // 渲染自定义分页器
  const renderCustomPaginator = () => {
    const totalPages = getTotalPages();
    return (
      <div className="p-paginator p-component">
        {/* 首页按钮 */}
        <Button
          icon="pi pi-angle-double-left"
          disabled={currentPage === 1}
          onClick={() => handlePageClick(1)}
          className="p-paginator-first"
        />
        {/* 上一页按钮 */}
        <Button
          icon="pi pi-angle-left"
          disabled={currentPage === 1}
          onClick={() => handlePageClick(currentPage - 1)}
          className="p-paginator-prev"
        />

        {/* 页码按钮组 */}
        {pageNumbers.map((page, idx) => (
          <Button
            key={idx}
            label={page}
            onClick={() => handlePageClick(page)}
            className={`p-paginator-page ${currentPage === page ? 'p-highlight' : ''}`}
            disabled={page === '...'}
          />
        ))}

        {/* 下一页按钮 */}
        <Button
          icon="pi pi-angle-right"
          disabled={currentPage === totalPages}
          onClick={() => handlePageClick(currentPage + 1)}
          className="p-paginator-next"
        />
        {/* 末页按钮 */}
        <Button
          icon="pi pi-angle-double-right"
          disabled={currentPage === totalPages}
          onClick={() => handlePageClick(totalPages)}
          className="p-paginator-last"
        />
      </div>
    );
  };

  return (
    <DataTable
      value={data}
      paginator
      rows={rowsPerPage}
      first={(currentPage - 1) * rowsPerPage}
      lazy={isLazy}
      totalRecords={totalRecords}
      onPageChange={(e) => setCurrentPage(e.page + 1)} // PrimeReact的page从0开始,转成1-based
      paginatorTemplate="CustomPaginator"
      customPaginatorTemplate={renderCustomPaginator()}
    >
      <Column field="id" header="ID" />
      <Column field="name" header="Name" />
      {/* 其他列定义 */}
    </DataTable>
  );
};

// 生成页码列表的工具函数
const generatePageNumbers = (currentPage, totalPages) => {
  const pages = [];
  if (totalPages <= 5) {
    for (let i = 1; i <= totalPages; i++) {
      pages.push(i);
    }
    return pages;
  }

  if (currentPage <= 3) {
    return [1, 2, 3, '...', totalPages];
  }

  if (currentPage >= totalPages - 2) {
    return [1, '...', totalPages - 2, totalPages - 1, totalPages];
  }

  return [1, '...', currentPage - 1, currentPage, currentPage + 1, '...', totalPages];
};

export default CustomPaginatorDataTable;

解决你遇到的具体问题

  1. 无法获取总页数:放弃依赖pageLinks,改用手动计算的方式(非懒加载用数据源长度,懒加载用totalRecords),避免pageLinks未初始化或结构变化导致的问题。
  2. 非懒加载模式下自定义模板无效:确保first属性正确设置为(currentPage - 1) * rowsPerPage,同时onPageChange正确更新currentPage,模板内总页数直接通过数据源长度计算,避免依赖外部失效参数。
  3. state存pageLinks总页数报错:直接跳过从pageLinks取总页数的逻辑,改用稳定的手动计算方式,避免pageLinks初始化时为undefined引发的报错。

样式适配

直接复用PrimeReact默认分页器的CSS类(如p-paginator、p-paginator-page、p-highlight),即可保持与原生组件一致的样式风格。

内容的提问来源于stack exchange,提问作者Yeagerist

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 23:53:12