我是 ReactJS 的新手,正在其中创建一个简单的 TODO 应用程序。实际上,它是一个非常基本的应用程序,没有数据库连接,任务存储在一个数组中。我添加了编辑和删除功能,现在我要添加分页。
我该如何实施呢? 任何帮助都将不胜感激。谢谢你... ! !
给你一个分页组件,这对于新手来说可能有点难以理解到 react:
react
Https://www.npmjs.com/package/pagination
我最近用纯 React JS 实现了分页
当然,您必须调整逻辑和显示页码的方式,以便满足您的需求。
完整代码:
class TodoApp extends React.Component { constructor() { super(); this.state = { todos: ['a','b','c','d','e','f','g','h','i','j','k'], currentPage: 1, todosPerPage: 3 }; this.handleClick = this.handleClick.bind(this); } handleClick(event) { this.setState({ currentPage: Number(event.target.id) }); } render() { const { todos, currentPage, todosPerPage } = this.state; // Logic for displaying todos const indexOfLastTodo = currentPage * todosPerPage; const indexOfFirstTodo = indexOfLastTodo - todosPerPage; const currentTodos = todos.slice(indexOfFirstTodo, indexOfLastTodo); const renderTodos = currentTodos.map((todo, index) => { return <li key={index}>{todo}</li>; }); // Logic for displaying page numbers const pageNumbers = []; for (let i = 1; i <= Math.ceil(todos.length / todosPerPage); i++) { pageNumbers.push(i); } const renderPageNumbers = pageNumbers.map(number => { return ( <li key={number} id={number} onClick={this.handleClick} > {number} </li> ); }); return ( <div> <ul> {renderTodos} </ul> <ul id="page-numbers"> {renderPageNumbers} </ul> </div> ); } } ReactDOM.render( <TodoApp />, document.getElementById('app') );
我最近创建了这个 Pagination 组件,它实现了像 Google 搜索结果这样的分页逻辑:
import React, { PropTypes } from 'react'; const propTypes = { items: PropTypes.array.isRequired, onChangePage: PropTypes.func.isRequired, initialPage: PropTypes.number } const defaultProps = { initialPage: 1 } class Pagination extends React.Component { constructor(props) { super(props); this.state = { pager: {} }; } componentWillMount() { this.setPage(this.props.initialPage); } setPage(page) { var items = this.props.items; var pager = this.state.pager; if (page < 1 || page > pager.totalPages) { return; } // get new pager object for specified page pager = this.getPager(items.length, page); // get new page of items from items array var pageOfItems = items.slice(pager.startIndex, pager.endIndex + 1); // update state this.setState({ pager: pager }); // call change page function in parent component this.props.onChangePage(pageOfItems); } getPager(totalItems, currentPage, pageSize) { // default to first page currentPage = currentPage || 1; // default page size is 10 pageSize = pageSize || 10; // calculate total pages var totalPages = Math.ceil(totalItems / pageSize); var startPage, endPage; if (totalPages <= 10) { // less than 10 total pages so show all startPage = 1; endPage = totalPages; } else { // more than 10 total pages so calculate start and end pages if (currentPage <= 6) { startPage = 1; endPage = 10; } else if (currentPage + 4 >= totalPages) { startPage = totalPages - 9; endPage = totalPages; } else { startPage = currentPage - 5; endPage = currentPage + 4; } } // calculate start and end item indexes var startIndex = (currentPage - 1) * pageSize; var endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1); // create an array of pages to ng-repeat in the pager control var pages = _.range(startPage, endPage + 1); // return object with all pager properties required by the view return { totalItems: totalItems, currentPage: currentPage, pageSize: pageSize, totalPages: totalPages, startPage: startPage, endPage: endPage, startIndex: startIndex, endIndex: endIndex, pages: pages }; } render() { var pager = this.state.pager; return ( <ul className="pagination"> <li className={pager.currentPage === 1 ? 'disabled' : ''}> <a onClick={() => this.setPage(1)}>First</a> </li> <li className={pager.currentPage === 1 ? 'disabled' : ''}> <a onClick={() => this.setPage(pager.currentPage - 1)}>Previous</a> </li> {pager.pages.map((page, index) => <li key={index} className={pager.currentPage === page ? 'active' : ''}> <a onClick={() => this.setPage(page)}>{page}</a> </li> )} <li className={pager.currentPage === pager.totalPages ? 'disabled' : ''}> <a onClick={() => this.setPage(pager.currentPage + 1)}>Next</a> </li> <li className={pager.currentPage === pager.totalPages ? 'disabled' : ''}> <a onClick={() => this.setPage(pager.totalPages)}>Last</a> </li> </ul> ); } } Pagination.propTypes = propTypes; Pagination.defaultProps export default Pagination;
下面是一个示例 App 组件,它使用 Pagination 组件对包含150个示例项的列表进行分页:
import React from 'react'; import Pagination from './Pagination'; class App extends React.Component { constructor() { super(); // an example array of items to be paged var exampleItems = _.range(1, 151).map(i => { return { id: i, name: 'Item ' + i }; }); this.state = { exampleItems: exampleItems, pageOfItems: [] }; // bind function in constructor instead of render (https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md) this.onChangePage = this.onChangePage.bind(this); } onChangePage(pageOfItems) { // update state with new page of items this.setState({ pageOfItems: pageOfItems }); } render() { return ( <div> <div className="container"> <div className="text-center"> <h1>React - Pagination Example with logic like Google</h1> {this.state.pageOfItems.map(item => <div key={item.id}>{item.name}</div> )} <Pagination items={this.state.exampleItems} onChangePage={this.onChangePage} /> </div> </div> <hr /> <div className="credits text-center"> <p> <a href="http://jasonwatmore.com" target="_top">JasonWatmore.com</a> </p> </div> </div> ); } } export default App;
更多的细节和一个现场演示,你可以查看 这篇文章
Sample pagination react js working code import React, { Component } from 'react'; import { Pagination, PaginationItem, PaginationLink } from "reactstrap"; let prev = 0; let next = 0; let last = 0; let first = 0; export default class SamplePagination extends Component { constructor() { super(); this.state = { todos: ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','T','v','u','w','x','y','z'], currentPage: 1, todosPerPage: 3, }; this.handleClick = this.handleClick.bind(this); this.handleLastClick = this.handleLastClick.bind(this); this.handleFirstClick = this.handleFirstClick.bind(this); } handleClick(event) { event.preventDefault(); this.setState({ currentPage: Number(event.target.id) }); } handleLastClick(event) { event.preventDefault(); this.setState({ currentPage:last }); } handleFirstClick(event) { event.preventDefault(); this.setState({ currentPage:1 }); } render() { let { todos, currentPage, todosPerPage } = this.state; // Logic for displaying current todos let indexOfLastTodo = currentPage * todosPerPage; let indexOfFirstTodo = indexOfLastTodo - todosPerPage; let currentTodos = todos.slice(indexOfFirstTodo, indexOfLastTodo); prev = currentPage > 0 ? (currentPage -1) :0; last = Math.ceil(todos.length/todosPerPage); next = (last === currentPage) ?currentPage: currentPage +1; // Logic for displaying page numbers let pageNumbers = []; for (let i = 1; i <=last; i++) { pageNumbers.push(i); } return ( <div> <ul> { currentTodos.map((todo,index) =>{ return <li key={index}>{todo}</li>; }) } </ul><ul id="page-numbers"> <nav> <Pagination> <PaginationItem> { prev === 0 ? <PaginationLink disabled>First</PaginationLink> : <PaginationLink onClick={this.handleFirstClick} id={prev} href={prev}>First</PaginationLink> } </PaginationItem> <PaginationItem> { prev === 0 ? <PaginationLink disabled>Prev</PaginationLink> : <PaginationLink onClick={this.handleClick} id={prev} href={prev}>Prev</PaginationLink> } </PaginationItem> { pageNumbers.map((number,i) => <Pagination key= {i}> <PaginationItem active = {pageNumbers[currentPage-1] === (number) ? true : false} > <PaginationLink onClick={this.handleClick} href={number} key={number} id={number}> {number} </PaginationLink> </PaginationItem> </Pagination> )} <PaginationItem> { currentPage === last ? <PaginationLink disabled>Next</PaginationLink> : <PaginationLink onClick={this.handleClick} id={pageNumbers[currentPage]} href={pageNumbers[currentPage]}>Next</PaginationLink> } </PaginationItem> <PaginationItem> { currentPage === last ? <PaginationLink disabled>Last</PaginationLink> : <PaginationLink onClick={this.handleLastClick} id={pageNumbers[currentPage]} href={pageNumbers[currentPage]}>Last</PaginationLink> } </PaginationItem> </Pagination> </nav> </ul> </div> ); } } ReactDOM.render( <SamplePagination />, document.getElementById('root') );
我最近创建了一个库,可以帮助处理如下分页情况:
页面实现了上述所有特性。
你可以在 Github上找到源代码
我已经尝试重新创建由 Piotr-Berebecki给出的简单分页示例,这是伟大的。但是当有很多页面时,分页就会在屏幕上溢出。因此,我使用了前后按钮以及前后按钮来在页面之间来回流动。在设计部分我使用了自举3。
可以使用页绑定值自定义在分页中显示的任何页。确保 upperPageBound 和 pageBound 使用相同的值。
class TodoApp extends React.Component { constructor() { super(); this.state = { todos: ['a','b','c','d','e','f','g','h','i','j','k','l','m', 'n','o','p','q','r','s','t','u','v','w','x','y','z'], currentPage: 1, todosPerPage: 3, upperPageBound: 3, lowerPageBound: 0, isPrevBtnActive: 'disabled', isNextBtnActive: '', pageBound: 3 }; this.handleClick = this.handleClick.bind(this); this.btnDecrementClick = this.btnDecrementClick.bind(this); this.btnIncrementClick = this.btnIncrementClick.bind(this); this.btnNextClick = this.btnNextClick.bind(this); this.btnPrevClick = this.btnPrevClick.bind(this); // this.componentDidMount = this.componentDidMount.bind(this); this.setPrevAndNextBtnClass = this.setPrevAndNextBtnClass.bind(this); } componentDidUpdate() { $("ul li.active").removeClass('active'); $('ul li#'+this.state.currentPage).addClass('active'); } handleClick(event) { let listid = Number(event.target.id); this.setState({ currentPage: listid }); $("ul li.active").removeClass('active'); $('ul li#'+listid).addClass('active'); this.setPrevAndNextBtnClass(listid); } setPrevAndNextBtnClass(listid) { let totalPage = Math.ceil(this.state.todos.length / this.state.todosPerPage); this.setState({isNextBtnActive: 'disabled'}); this.setState({isPrevBtnActive: 'disabled'}); if(totalPage === listid && totalPage > 1){ this.setState({isPrevBtnActive: ''}); } else if(listid === 1 && totalPage > 1){ this.setState({isNextBtnActive: ''}); } else if(totalPage > 1){ this.setState({isNextBtnActive: ''}); this.setState({isPrevBtnActive: ''}); } } btnIncrementClick() { this.setState({upperPageBound: this.state.upperPageBound + this.state.pageBound}); this.setState({lowerPageBound: this.state.lowerPageBound + this.state.pageBound}); let listid = this.state.upperPageBound + 1; this.setState({ currentPage: listid}); this.setPrevAndNextBtnClass(listid); } btnDecrementClick() { this.setState({upperPageBound: this.state.upperPageBound - this.state.pageBound}); this.setState({lowerPageBound: this.state.lowerPageBound - this.state.pageBound}); let listid = this.state.upperPageBound - this.state.pageBound; this.setState({ currentPage: listid}); this.setPrevAndNextBtnClass(listid); } btnPrevClick() { if((this.state.currentPage -1)%this.state.pageBound === 0 ){ this.setState({upperPageBound: this.state.upperPageBound - this.state.pageBound}); this.setState({lowerPageBound: this.state.lowerPageBound - this.state.pageBound}); } let listid = this.state.currentPage - 1; this.setState({ currentPage : listid}); this.setPrevAndNextBtnClass(listid); } btnNextClick() { if((this.state.currentPage +1) > this.state.upperPageBound ){ this.setState({upperPageBound: this.state.upperPageBound + this.state.pageBound}); this.setState({lowerPageBound: this.state.lowerPageBound + this.state.pageBound}); } let listid = this.state.currentPage + 1; this.setState({ currentPage : listid}); this.setPrevAndNextBtnClass(listid); } render() { const { todos, currentPage, todosPerPage,upperPageBound,lowerPageBound,isPrevBtnActive,isNextBtnActive } = this.state; // Logic for displaying current todos const indexOfLastTodo = currentPage * todosPerPage; const indexOfFirstTodo = indexOfLastTodo - todosPerPage; const currentTodos = todos.slice(indexOfFirstTodo, indexOfLastTodo); const renderTodos = currentTodos.map((todo, index) => { return <li key={index}>{todo}</li>; }); // Logic for displaying page numbers const pageNumbers = []; for (let i = 1; i <= Math.ceil(todos.length / todosPerPage); i++) { pageNumbers.push(i); } const renderPageNumbers = pageNumbers.map(number => { if(number === 1 && currentPage === 1){ return( <li key={number} className='active' id={number}><a href='#' id={number} onClick={this.handleClick}>{number}</a></li> ) } else if((number < upperPageBound + 1) && number > lowerPageBound){ return( <li key={number} id={number}><a href='#' id={number} onClick={this.handleClick}>{number}</a></li> ) } }); let pageIncrementBtn = null; if(pageNumbers.length > upperPageBound){ pageIncrementBtn = <li className=''><a href='#' onClick={this.btnIncrementClick}> … </a></li> } let pageDecrementBtn = null; if(lowerPageBound >= 1){ pageDecrementBtn = <li className=''><a href='#' onClick={this.btnDecrementClick}> … </a></li> } let renderPrevBtn = null; if(isPrevBtnActive === 'disabled') { renderPrevBtn = <li className={isPrevBtnActive}><span id="btnPrev"> Prev </span></li> } else{ renderPrevBtn = <li className={isPrevBtnActive}><a href='#' id="btnPrev" onClick={this.btnPrevClick}> Prev </a></li> } let renderNextBtn = null; if(isNextBtnActive === 'disabled') { renderNextBtn = <li className={isNextBtnActive}><span id="btnNext"> Next </span></li> } else{ renderNextBtn = <li className={isNextBtnActive}><a href='#' id="btnNext" onClick={this.btnNextClick}> Next </a></li> } return ( <div> <ul> {renderTodos} </ul> <ul id="page-numbers" className="pagination"> {renderPrevBtn} {pageDecrementBtn} {renderPageNumbers} {pageIncrementBtn} {renderNextBtn} </ul> </div> ); } } ReactDOM.render( <TodoApp />, document.getElementById('app') );
工作演示链接: https://codepen.io/mhmanandhar/pen/oEWBqx
图片来源: 简单反应式分页法
这里有一种方法来创建您的自定义分页组件从反应引导库和这个组件,您可以使用整个项目
您的分页组件(Pagination.jsx 或 js)
import React, { Component } from "react"; import { Pagination } from "react-bootstrap"; import PropTypes from "prop-types"; export default class PaginationHandler extends Component { constructor(props) { super(props); this.state = { paging: { offset: 0, limit: 10 }, active: 0 }; } pagingHandler = () => { let offset = parseInt(event.target.id); this.setState({ active: offset }); this.props.pageHandler(event.target.id - 1); }; nextHandler = () => { let active = this.state.active; this.setState({ active: active + 1 }); this.props.pageHandler(active + 1); }; backHandler = () => { let active = this.state.active; this.setState({ active: active - 1 }); this.props.pageHandler(active - 1); }; renderPageNumbers = (pageNumbers, totalPages) => { let { active } = this.state; return ( <Pagination> <Pagination.Prev disabled={active < 5} onClick={ active >5 && this.backHandler} /> { pageNumbers.map(number => { if ( number >= parseInt(active) - 3 && number <= parseInt(active) + 3 ) { return ( <Pagination.Item id={number} active={number == active} onClick={this.pagingHandler} > {number} </Pagination.Item> ); } else { return null; } })} <Pagination.Next onClick={ active <= totalPages -4 && this.nextHandler} /> </Pagination> ); }; buildComponent = (props, state) => { const { totalPages } = props; const pageNumbers = []; for (let i = 1; i <= totalPages; i++) { pageNumbers.push(i); } return ( <div className="pull-right"> {this.renderPageNumbers(pageNumbers ,totalPages)} </div> ); }; render() { return this.buildComponent(this.props, this.state); } } PaginationHandler.propTypes = { paging: PropTypes.object, pageHandler: PropTypes.func, totalPages: PropTypes.object };
在父组件中使用以上子组件,如下所示
import Pagination from "../pagination"; pageHandler = (offset) =>{ this.setState(({ paging }) => ({ paging: { ...paging, offset: offset } })); } render() { return ( <div> <Pagination paging = {paging} pageHandler = {this.pageHandler} totalPages = {totalPages}> </Pagination> </div> ); }
一个 ReactJS 哑组件来呈现分页。你也可以使用这个库:
https://www.npmjs.com/package/react-js-pagination
以下是一些例子:
Http://vayser.github.io/react-js-pagination/
或者
你也可以使用这个 https://codepen.io/PiotrBerebecki/pen/pEYPbY
确保它作为一个单独的组件 我曾经使用过 < a href = “ http://tabler-react.com”rel = “ nofollow norefrer”> tabler-response
import * as React from "react"; import { Page, Button } from "tabler-react"; class PaginateComponent extends React.Component { constructor(props) { super(props); this.state = { array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], limit: 5, // optional page: 1 }; } paginateValue = (page) => { this.setState({ page: page }); console.log(page) // access this value from parent component } paginatePrevValue = (page) => { this.setState({ page: page }); console.log(page) // access this value from parent component } paginateNxtValue = (page) => { this.setState({ page: page }); console.log(page) // access this value from parent component } render() { return ( <div> <div> <Button.List> <Button disabled={this.state.page === 0} onClick={() => this.paginatePrevValue(this.state.page - 1)} outline color="primary" > Previous </Button> {this.state.array.map((value, index) => { return ( <Button onClick={() => this.paginateValue(value)} color={ this.state.page === value ? "primary" : "secondary" } > {value} </Button> ); })} <Button onClick={() => this.paginateNxtValue(this.state.page + 1)} outline color="secondary" > Next </Button> </Button.List> </div> </div> ) } } export default PaginateComponent;
我已经在 ReactJ 中实现了分页 + 搜索,请看输出: 反应中的分页
在 GitHub 上查看完整代码: https://github.com/navanathjadhav/generic-pagination
还可以访问本文,了解分页的分步实现: https://everblogs.com/react/3-simple-steps-to-add-pagination-in-react/
请参见代码和框中的代码示例
Https://codesandbox.io/s/pagino-13pit
import Pagino from "pagino"; import { useState, useMemo } from "react"; export default function App() { const [pages, setPages] = useState([]); const pagino = useMemo(() => { const _ = new Pagino({ showFirst: false, showLast: false, onChange: (page, count) => setPages(_.getPages()) }); _.setCount(10); return _; }, []); const hanglePaginoNavigation = (type) => { if (typeof type === "string") { pagino[type]?.(); return; } pagino.setPage(type); }; return ( <div> <h1>Page: {pagino.page}</h1> <ul> {pages.map((page) => ( <button key={page} onClick={() => hanglePaginoNavigation(page)}> {page} </button> ))} </ul> </div> ); }
1-使用 react-bootstrap
react-bootstrap
import React from "react"; import { Pagination } from "react-bootstrap"; import Link from "next/link"; interface PaginateProps { pages: number; page: number; keyword?: string; isAdmin?: boolean; } const Paginate = ({ pages, page, // keyword is for searching keyword = "", isAdmin = false, }: PaginateProps) => { return pages > 1 ? ( <Pagination> {/* keys returns a new Array iterator contians the keys for each index */} // pages is total number of pages {[...Array(pages).keys()].map((x) => ( // this is next.js component. you could use react Link <Link passHref key={x + 1} href={ !isAdmin // since array indexing starts at 0, use x+1 ? `/?keyword=${keyword}&page=${x + 1}` : `/admin/productlist/?keyword=${keyword}&page=${x + 1}` } > <Pagination.Item active={x + 1 === page}>{x + 1}</Pagination.Item> </Link> ))} </Pagination> ) : null; }; export default Paginate;
然后在页面中使用它。
<Paginate page={page} pages={pages} keyword={keyword} />
2-use response-js pagination 2-使用 response-js 分页
import Pagination from "react-js-pagination"; // bootstrap class to center <div className="d-flex justify-content-center mt-5"> <Pagination activePage={page} itemsCountPerPage={resPerPageValue} totalItemsCount={Count} onChange={handlePagination} nextPageText={"Next"} prevPageText={"Prev"} firstPageText={"First"} lastPageText={"Last"} // overwriting the style itemClass="page-item" linkClass="page-link" /> </div>
OnChange 处理程序
const handlePagination = (pageNumber) => { // window.location.href will reload entire page router.push(`/?page=${pageNumber}`); };