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

如何在React Bootstrap分页中动态添加Pagination.Ellipsis?

在React Bootstrap分页组件中添加Pagination.Ellipsis的问题

我现有的API数据及分页组件(包含Pagination.First、Pagination.Prev、Pagination.Item、Pagination.Next和Pagination.Last)运行正常,但不知道如何在其中添加Pagination.Ellipsis来折叠过多的页码。我尝试过直接使用<Pagination.Ellipsis key={pageNumbers} className="muted" />以及一段判断添加省略号的代码,但都没有生效。


现有代码

MovieList.js

import { React, useState, useEffect } from "react";
import { Col, Card, Row, Pagination } from "react-bootstrap";
import MovieListPagination from "./MovieListPagination";

const MovieList = () => {
  const [error, setError] = useState(null);
  const [isLoaded, setIsLoaded] = useState(false);
  const [items, setItems] = useState([]);
  // 默认当前页和每页条数
  const [currentPage, setCurrentPage] = useState(1);
  const [postsPerPage] = useState(4);
  // 获取当前页数据
  const indexOfLastPost = currentPage * postsPerPage;
  const indexOfFirstPost = indexOfLastPost - postsPerPage;
  const currentPosts = items.slice(indexOfFirstPost, indexOfLastPost);
  // 切换页面
  const paginate = (pageNumber) => setCurrentPage(pageNumber);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/posts")
      .then((res) => res.json())
      .then(
        (result) => {
          setIsLoaded(true);
          setItems(result);
        },
        (error) => {
          setIsLoaded(true);
          setError(error);
        }
      );
  }, []);

  if (error) {
    return <div className="p-3">Error: {error.message}</div>;
  } else if (!isLoaded) {
    return <div className="p-3">Loading...</div>;
  } else {
    return (
      <>
        <Row className="justify-content-center">
          {currentPosts.map((item) => (
            <Col sm={6} lg={4} xl={3} className="py-3" key={item.id}>
              <Card bg="dark" text="light" className="text-center h-100">
                <Card.Body>
                  <Card.Title>{item.title}</Card.Title>
                  <Card.Text>{item.body}</Card.Text>
                </Card.Body>
              </Card>
            </Col>
          ))}
          <Pagination className="justify-content-center">
            <MovieListPagination
              currentPage={currentPage}
              postsPerPage={postsPerPage}
              totalPosts={items.length}
              paginate={paginate}
            />
          </Pagination>
        </Row>
      </>
    );
  }
};

export default MovieList;

MovieListPagination.js

import { React } from "react";
import { Pagination } from "react-bootstrap";

const MovieListPagination = ({
  currentPage,
  postsPerPage,
  totalPosts,
  paginate
}) => {
  const pageNumbers = [];
  const pagesCount = Math.ceil(totalPosts / postsPerPage);
  const isCurrentPageFirst = currentPage === 1;
  const isCurrentPageLast = currentPage === pagesCount;
  for (let i = 1; i <= pagesCount; i++) {
    pageNumbers.push(i);
  }
  return (
    <>
      <Pagination.First onClick={() => paginate(1)} />
      <Pagination.Prev
        onClick={() => paginate(currentPage - 1)}
        disabled={isCurrentPageFirst}
      />
      {pageNumbers.map((number) => (
        <Pagination.Item
          key={number}
          className={`${currentPage === number ? "active" : ""}`}
          onClick={() => {
            paginate(number);
          }}
        >
          {number}
        </Pagination.Item>
      ))}
      <Pagination.Next
        onClick={() => paginate(currentPage + 1)}
        disabled={isCurrentPageLast}
      />
      <Pagination.Last onClick={() => paginate(pagesCount)} />
    </>
  );
};

export default MovieListPagination;

尝试过的无效代码

// 添加省略号以折叠更多页码
if (pageNumbers[0] > 1) {
  pageNumbers.unshift(<Pagination.Ellipsis key="ellipsis-start" />);
}
if (pageNumbers[pageNumbers.length - 1] < totalPosts) {
  pageNumbers.push(<Pagination.Ellipsis key="ellipsis-end" />);
}

解决方案

问题出在直接把React元素塞进数字数组,且判断逻辑不符合分页显示规则。正确做法是根据当前页和总页数,动态生成包含页码和省略号的元素列表:

修改MovieListPagination.js代码如下:

import { React } from "react";
import { Pagination } from "react-bootstrap";

const MovieListPagination = ({
  currentPage,
  postsPerPage,
  totalPosts,
  paginate
}) => {
  const pagesCount = Math.ceil(totalPosts / postsPerPage);
  const isCurrentPageFirst = currentPage === 1;
  const isCurrentPageLast = currentPage === pagesCount;
  const paginationItems = [];

  // 始终显示第一页
  if (pagesCount > 0) {
    paginationItems.push(
      <Pagination.Item
        key={1}
        active={currentPage === 1}
        onClick={() => paginate(1)}
      >
        1
      </Pagination.Item>
    );
  }

  // 当前页距离第一页超过2时,添加前省略号
  if (currentPage > 3) {
    paginationItems.push(<Pagination.Ellipsis key="prev-ellipsis" />);
  }

  // 显示当前页前后各1个页码
  const startPage = Math.max(2, currentPage - 1);
  const endPage = Math.min(pagesCount - 1, currentPage + 1);
  for (let i = startPage; i <= endPage; i++) {
    paginationItems.push(
      <Pagination.Item
        key={i}
        active={currentPage === i}
        onClick={() => paginate(i)}
      >
        {i}
      </Pagination.Item>
    );
  }

  // 当前页距离最后一页超过2时,添加后省略号
  if (currentPage < pagesCount - 2) {
    paginationItems.push(<Pagination.Ellipsis key="next-ellipsis" />);
  }

  // 始终显示最后一页(总页数大于1时)
  if (pagesCount > 1) {
    paginationItems.push(
      <Pagination.Item
        key={pagesCount}
        active={currentPage === pagesCount}
        onClick={() => paginate(pagesCount)}
      >
        {pagesCount}
      </Pagination.Item>
    );
  }

  return (
    <>
      <Pagination.First onClick={() => paginate(1)} />
      <Pagination.Prev
        onClick={() => paginate(currentPage - 1)}
        disabled={isCurrentPageFirst}
      />
      {paginationItems}
      <Pagination.Next
        onClick={() => paginate(currentPage + 1)}
        disabled={isCurrentPageLast}
      />
      <Pagination.Last onClick={() => paginate(pagesCount)} />
    </>
  );
};

export default MovieListPagination;

代码说明

  • 始终保留第一页和最后一页的入口,避免用户无法快速跳转首尾
  • 仅在当前页距离首尾页足够远时显示省略号,保证分页栏简洁
  • 只展示当前页前后各1个页码,平衡可用性和美观性
  • 使用官方Pagination.Ellipsis组件,符合React Bootstrap样式规范

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 13:18:10