如何在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
相关产品推荐
相关产品推荐

