ReactJS - 分页



React 通过第三方 UI 组件库提供分页组件。React 社区提供了大量的 UI/UX 组件,很难为我们的需求选择合适的库。Bootstrap UI 库是开发人员的热门选择之一,它被广泛使用。React Bootstrap (https://react-bootstrap.github.io/) 移植了几乎所有的 Bootstrap UI 组件,并且对分页组件也有最好的支持。

在本章中,让我们学习如何使用 react-bootstrap 库中的分页组件。

分页组件

分页组件允许开发人员在 Web 应用程序中使用 Bootstrap 设计创建简单的分页。分页组件接受以下组件。

  • 分页.Item
  • 分页.First
  • 分页.Last
  • 分页.Previous
  • 分页.Next

分页组件接受一小组属性来自定义分页组件,它们如下 -

  • 尺寸 (SM | LG)
  • 设置分页按钮的大小
  • bsPrefix(字符串)
  • 允许更改底层组件 CSS

Pagination.Item 组件接受一小组 props 来自定义分页组件,它们如下所示 -

  • 活动(布尔值)
  • 将项目设置为活动项目,并且不呈现标记。
  • activeLabel(字符串)
  • 用于指示分页项状态的标签
  • 已禁用(布尔值)
  • 禁用分页项
  • href (字符串)
  • 分页项的链接
  • onClick(函数)
  • 触发 onClick 事件时要调用的回调函数

应用分页组件

首先,创建一个新的 react 应用程序并使用以下命令启动它。

create-react-app myapp
cd myapp
npm start

接下来,使用以下命令安装 bootstrap 库,

npm install --save bootstrap react-bootstrap

接下来,打开 App.css (src/App.css) 并删除所有 CSS 类。

// remove the css

接下来,创建一个简单的分页组件 SimplePagination (src/Components/SimplePagination.js),如下所示:


import React from 'react';
import { Table, Pagination } from 'react-bootstrap';
class SimplePagination extends React.Component {
	 	render() {
	 	 	 <div>Pagination component</div>
	 	}
}
export default SimplePagination;

接下来,创建一个文件,users.json公共文件夹下,并填充下面的用户信息,


[
	 	{
	 	 	 "id":1,
	 	 	 "name":"Fowler",
	 	 	 "age":18
	 	},
	 	{
	 	 	 "id":2,
	 	 	 "name":"Donnell",
	 	 	 "age":24
	 	},
	 	{
	 	 	 "id":3,
	 	 	 "name":"Pall",
	 	 	 "age":26
	 	},
	 	{
	 	 	 "id":4,
	 	 	 "name":"Christos",
	 	 	 "age":19
	 	},
	 	{
	 	 	 "id":5,
	 	 	 "name":"Dud",
	 	 	 "age":29
	 	},
	 	{
	 	 	 "id":6,
	 	 	 "name":"Rayner",
	 	 	 "age":22
	 	},
	 	{
	 	 	 "id":7,
	 	 	 "name":"Somerset",
	 	 	 "age":31
	 	},
	 	{
	 	 	 "id":8,
	 	 	 "name":"Stavros",
	 	 	 "age":32
	 	},
	 	{
	 	 	 "id":9,
	 	 	 "name":"Cody",
	 	 	 "age":19
	 	},
	 	{
	 	 	 "id":10,
	 	 	 "name":"Sharai",
	 	 	 "age":19
	 	},
	 	{
	 	 	 "id":11,
	 	 	 "name":"Kristo",
	 	 	 "age":28
	 	},
	 	{
	 	 	 "id":12,
	 	 	 "name":"Harvey",
	 	 	 "age":27
	 	},
	 	{
	 	 	 "id":13,
	 	 	 "name":"Christen",
	 	 	 "age":27
	 	},
	 	{
	 	 	 "id":14,
	 	 	 "name":"Hillard",
	 	 	 "age":19
	 	},
	 	{
	 	 	 "id":15,
	 	 	 "name":"Jaine",
	 	 	 "age":32
	 	},
	 	{
	 	 	 "id":16,
	 	 	 "name":"Annabel",
	 	 	 "age":29
	 	},
	 	{
	 	 	 "id":17,
	 	 	 "name":"Hildagarde",
	 	 	 "age":29
	 	},
	 	{
	 	 	 "id":18,
	 	 	 "name":"Cherlyn",
	 	 	 "age":18
	 	},
	 	{
	 	 	 "id":19,
	 	 	 "name":"Herold",
	 	 	 "age":32
	 	},
	 	{
	 	 	 "id":20,
	 	 	 "name":"Gabriella",
	 	 	 "age":32
	 	},
	 	{
	 	 	 "id":21,
	 	 	 "name":"Jessalyn",
	 	 	 "age":32
	 	},
	 	{
	 	 	 "id":22,
	 	 	 "name":"Opal",
	 	 	 "age":31
	 	},
	 	{
	 	 	 "id":23,
	 	 	 "name":"Westbrooke",
	 	 	 "age":27
	 	},
	 	{
	 	 	 "id":24,
	 	 	 "name":"Morey",
	 	 	 "age":22
	 	},
	 	{
	 	 	 "id":25,
	 	 	 "name":"Carleton",
	 	 	 "age":26
	 	},
	 	{
	 	 	 "id":26,
	 	 	 "name":"Cosimo",
	 	 	 "age":22
	 	},
	 	{
	 	 	 "id":27,
	 	 	 "name":"Petronia",
	 	 	 "age":23
	 	},
	 	{
	 	 	 "id":28,
	 	 	 "name":"Justino",
	 	 	 "age":32
	 	},
	 	{
	 	 	 "id":29,
	 	 	 "name":"Verla",
	 	 	 "age":20
	 	},
	 	{
	 	 	 "id":30,
	 	 	 "name":"Lanita",
	 	 	 "age":18
	 	},
	 	{
	 	 	 "id":31,
	 	 	 "name":"Karlik",
	 	 	 "age":23
	 	},
	 	{
	 	 	 "id":32,
	 	 	 "name":"Emmett",
	 	 	 "age":22
	 	},
	 	{
	 	 	 "id":33,
	 	 	 "name":"Abran",
	 	 	 "age":26
	 	},
	 	{
	 	 	 "id":34,
	 	 	 "name":"Holly",
	 	 	 "age":23
	 	},
	 	{
	 	 	 "id":35,
	 	 	 "name":"Beverie",
	 	 	 "age":23
	 	},
	 	{
	 	 	 "id":36,
	 	 	 "name":"Ingelbert",
	 	 	 "age":27
	 	},
	 	{
	 	 	 "id":37,
	 	 	 "name":"Kailey",
	 	 	 "age":30
	 	},
	 	{
	 	 	 "id":38,
	 	 	 "name":"Ralina",
	 	 	 "age":26
	 	},
	 	{
	 	 	 "id":39,
	 	 	 "name":"Stella",
	 	 	 "age":29
	 	},
	 	{
	 	 	 "id":40,
	 	 	 "name":"Ronnica",
	 	 	 "age":20
	 	},
	 	{
	 	 	 "id":41,
	 	 	 "name":"Brucie",
	 	 	 "age":20
	 	},
	 	{
	 	 	 "id":42,
	 	 	 "name":"Ryan",
	 	 	 "age":22
	 	},
	 	{
	 	 	 "id":43,
	 	 	 "name":"Fredek",
	 	 	 "age":20
	 	},
	 	{
	 	 	 "id":44,
	 	 	 "name":"Corliss",
	 	 	 "age":28
	 	},
	 	{
	 	 	 "id":45,
	 	 	 "name":"Kary",
	 	 	 "age":32
	 	},
	 	{
	 	 	 "id":46,
	 	 	 "name":"Kaylee",
	 	 	 "age":21
	 	},
	 	{
	 	 	 "id":47,
	 	 	 "name":"Haskell",
	 	 	 "age":25
	 	},
	 	{
	 	 	 "id":48,
	 	 	 "name":"Jere",
	 	 	 "age":29
	 	},
	 	{
	 	 	 "id":49,
	 	 	 "name":"Kathryne",
	 	 	 "age":31
	 	},
	 	{
	 	 	 "id":50,
	 	 	 "name":"Linnea",
	 	 	 "age":21
	 	},
	 	{
	 	 	 "id":51,
	 	 	 "name":"Theresina",
	 	 	 "age":24
	 	},
	 	{
	 	 	 "id":52,
	 	 	 "name":"Arabela",
	 	 	 "age":32
	 	},
	 	{
	 	 	 "id":53,
	 	 	 "name":"Howie",
	 	 	 "age":22
	 	},
	 	{
	 	 	 "id":54,
	 	 	 "name":"Merci",
	 	 	 "age":21
	 	},
	 	{
	 	 	 "id":55,
	 	 	 "name":"Mitchel",
	 	 	 "age":30
	 	},
	 	{
	 	 	 "id":56,
	 	 	 "name":"Clari",
	 	 	 "age":18
	 	},
	 	{
	 	 	 "id":57,
	 	 	 "name":"Laurena",
	 	 	 "age":19
	 	},
	 	{
	 	 	 "id":58,
	 	 	 "name":"Odessa",
	 	 	 "age":30
	 	},
	 	{
	 	 	 "id":59,
	 	 	 "name":"Pippy",
	 	 	 "age":25
	 	},
	 	{
	 	 	 "id":60,
	 	 	 "name":"Wilmar",
	 	 	 "age":23
	 	},
	 	{
	 	 	 "id":61,
	 	 	 "name":"Cherianne",
	 	 	 "age":24
	 	},
	 	{
	 	 	 "id":62,
	 	 	 "name":"Huberto",
	 	 	 "age":25
	 	},
	 	{
	 	 	 "id":63,
	 	 	 "name":"Ariella",
	 	 	 "age":26
	 	},
	 	{
	 	 	 "id":64,
	 	 	 "name":"Lorant",
	 	 	 "age":30
	 	},
	 	{
	 	 	 "id":65,
	 	 	 "name":"Francesca",
	 	 	 "age":25
	 	},
	 	{
	 	 	 "id":66,
	 	 	 "name":"Ingamar",
	 	 	 "age":28
	 	},
	 	{
	 	 	 "id":67,
	 	 	 "name":"Myrta",
	 	 	 "age":27
	 	},
	 	{
	 	 	 "id":68,
	 	 	 "name":"Nicolette",
	 	 	 "age":26
	 	},
	 	{
	 	 	 "id":69,
	 	 	 "name":"Petra",
	 	 	 "age":22
	 	},
	 	{
	 	 	 "id":70,
	 	 	 "name":"Cyrill",
	 	 	 "age":27
	 	},
	 	{
	 	 	 "id":71,
	 	 	 "name":"Ad",
	 	 	 "age":23
	 	},
	 	{
	 	 	 "id":72,
	 	 	 "name":"Denys",
	 	 	 "age":22
	 	},
	 	{
	 	 	 "id":73,
	 	 	 "name":"Karilynn",
	 	 	 "age":23
	 	},
	 	{
	 	 	 "id":74,
	 	 	 "name":"Gunner",
	 	 	 "age":30
	 	},
	 	{
	 	 	 "id":75,
	 	 	 "name":"Falkner",
	 	 	 "age":20
	 	},
	 	{
	 	 	 "id":76,
	 	 	 "name":"Thurston",
	 	 	 "age":19
	 	},
	 	{
	 	 	 "id":77,
	 	 	 "name":"Codi",
	 	 	 "age":30
	 	},
	 	{
	 	 	 "id":78,
	 	 	 "name":"Jacob",
	 	 	 "age":31
	 	},
	 	{
	 	 	 "id":79,
	 	 	 "name":"Gasparo",
	 	 	 "age":26
	 	},
	 	{
	 	 	 "id":80,
	 	 	 "name":"Mitzi",
	 	 	 "age":29
	 	},
	 	{
	 	 	 "id":81,
	 	 	 "name":"Rubetta",
	 	 	 "age":21
	 	},
	 	{
	 	 	 "id":82,
	 	 	 "name":"Clary",
	 	 	 "age":20
	 	},
	 	{
	 	 	 "id":83,
	 	 	 "name":"Oliviero",
	 	 	 "age":24
	 	},
	 	{
	 	 	 "id":84,
	 	 	 "name":"Ranique",
	 	 	 "age":21
	 	},
	 	{
	 	 	 "id":85,
	 	 	 "name":"Shae",
	 	 	 "age":24
	 	},
	 	{
	 	 	 "id":86,
	 	 	 "name":"Woodrow",
	 	 	 "age":20
	 	},
	 	{
	 	 	 "id":87,
	 	 	 "name":"Junia",
	 	 	 "age":31
	 	},
	 	{
	 	 	 "id":88,
	 	 	 "name":"Athene",
	 	 	 "age":26
	 	},
	 	{
	 	 	 "id":89,
	 	 	 "name":"Veriee",
	 	 	 "age":18
	 	},
	 	{
	 	 	 "id":90,
	 	 	 "name":"Rickie",
	 	 	 "age":30
	 	},
	 	{
	 	 	 "id":91,
	 	 	 "name":"Carly",
	 	 	 "age":23
	 	},
	 	{
	 	 	 "id":92,
	 	 	 "name":"Vern",
	 	 	 "age":19
	 	},
	 	{
	 	 	 "id":93,
	 	 	 "name":"Trix",
	 	 	 "age":26
	 	},
	 	{
	 	 	 "id":94,
	 	 	 "name":"Lenore",
	 	 	 "age":20
	 	},
	 	{
	 	 	 "id":95,
	 	 	 "name":"Hanna",
	 	 	 "age":30
	 	},
	 	{
	 	 	 "id":96,
	 	 	 "name":"Dominique",
	 	 	 "age":21
	 	},
	 	{
	 	 	 "id":97,
	 	 	 "name":"Karlotta",
	 	 	 "age":22
	 	},
	 	{
	 	 	 "id":98,
	 	 	 "name":"Levey",
	 	 	 "age":20
	 	},
	 	{
	 	 	 "id":99,
	 	 	 "name":"Dalila",
	 	 	 "age":18
	 	},
	 	{
	 	 	 "id":100,
	 	 	 "name":"Launce",
	 	 	 "age":21
	 	}
]

接下来,在 SimplePagination 组件中添加一个构造函数,并设置初始状态,如下所示:


constructor(props) {
	 	super(props);
	 	this.state = {
	 	 	 users: [],
	 	 	 usersToBeShown: [],
	 	 	 currentPage: 1
	 	}
};

接下来,添加 componentDidMount 生命周期事件并添加以下代码以获取和处理用户信息。


componentDidMount() {
	 	fetch('users.json')
	 	 	 .then((response) => response.json())
	 	 	 .then((data) => {
	 	 	 	 	// console.log(data);
	 	 	 	 	this.setState({
	 	 	 	 	 	 users: data,
	 	 	 	 	 	 pageSize: 3,
	 	 	 	 	 	 usersToBeShown: [],
	 	 	 	 	 	 pageArray: []
	 	 	 	 	});
	 	 	 	 	this.calculatePaginationDetails(1)
	 	});
}

接下来,在calculatePaginationDetails方法中实现分页逻辑,如下所示:


calculatePaginationDetails = (page) => {
	 	console.log(page)
	 	let users = this.state.users;
	 	let total = users.length;
	 	let pages = Math.floor((users.length / this.state.pageSize) + 1);
	 	let firstPage = 1;
	 	let lastPage = pages;
	 	let pageArray = []
	 	let usersToBeShown = []
	 	let currentPage = 1;
	 	if(page.toString().toLowerCase().indexOf('previous') > 0) {
	 	 	 currentPage = this.state.currentPage - 1;
	 	 	 if(currentPage < 1) {
	 	 	 	 	currentPage = 1
	 	 	 }
	 	} else if(page.toString().toLowerCase().indexOf('next') > 0) {
	 	 	 currentPage = this.state.currentPage + 1;
	 	 	 if(currentPage > pages) {
	 	 	 	 	currentPage = pages;
	 	 	 }
	 	} else if(page.toString().toLowerCase().indexOf('first') > 0) {
	 	 	 currentPage = 1
	 	} else if(page.toString().toLowerCase().indexOf('last') > 0) {
	 	 	 currentPage = pages;
	 	} else {
	 	 	 currentPage = parseInt(page);
	 	}
	 	console.log(parseInt(page))
	 	console.log(currentPage)
	 	for(let i = currentPage; i <= currentPage + 4; i++) {
	 	 	 if(i <= pages)
	 	 	 pageArray.push(i)
	 	}
	 	let currentItemIndex = (currentPage - 1) * this.state.pageSize;
	 	for(let i = currentItemIndex; i < currentItemIndex + 3 && i <= (total - 1); i++) {
	 	 	 usersToBeShown.push(users[i])
	 	}
	 	let updatedState = {
	 	 	 usersToBeShown: usersToBeShown,
	 	 	 pageArray: pageArray,
	 	 	 firstPage: firstPage,
	 	 	 lastPage: lastPage,
	 	 	 currentPage: currentPage
	 	}
	 	console.log(updatedState)
	 	this.setState({
	 	 	 usersToBeShown: usersToBeShown,
	 	 	 pageArray: pageArray,
	 	 	 firstPage: firstPage,
	 	 	 lastPage: lastPage,
	 	 	 currentPage: currentPage
	 	});
}

接下来,添加一个事件处理程序来处理分页,并根据用户选择的页面设置数据,如下所示 :


handlePagination = (e) => {
	 	e.preventDefault();
	 	console.log(e.target);
	 	if(e.target.text != undefined) {
	 	 	 this.calculatePaginationDetails(e.target.text);
	 	}
}

接下来,使用 Table 组件呈现数据,并使用 Pagination 组件进行分页。


render() {
	 	return (
	 	 	 <>
	 	 	 	 	<Table bordered hover striped>
	 	 	 	 	 	 <thead>
	 	 	 	 	 	 	 	<tr>
	 	 	 	 	 	 	 	 	 <th>#</th>
	 	 	 	 	 	 	 	 	 <th>Name</th>
	 	 	 	 	 	 	 	 	 <th>Age</th>
	 	 	 	 	 	 	 	 	 <th>Email</th>
	 	 	 	 	 	 	 	</tr>
	 	 	 	 	 	 </thead>
	 	 	 	 	 	 <tbody>{
	 	 	 	 	 	 	 	this.state.usersToBeShown && this.state.usersToBeShown.length &&
	 	 	 	 	 	 	 	this.state.usersToBeShown.map(
	 	 	 	 	 	 	 	 	 (item) => (
	 	 	 	 	 	 	 	 	 	 	<tr key={item.id}>
	 	 	 	 	 	 	 	 	 	 	 	 <td>{item.id}</td>
	 	 	 	 	 	 	 	 	 	 	 	 <td>{item.name}</td>
	 	 	 	 	 	 	 	 	 	 	 	 <td>{item.age}</td>
	 	 	 	 	 	 	 	 	 	 	 	 <td>{item.name.toLowerCase()}.example@Qikepu.com</td>
	 	 	 	 	 	 	 	 	 	 	</tr>
	 	 	 	 	 	 	 	 	 )
	 	 	 	 	 	 	 	)
	 	 	 	 	 	 }
	 	 	 	 	 	 </tbody>
	 	 	 	 	</Table>
	 	 	 	 	<Pagination>
	 	 	 	 	 	 <Pagination.First onClick={(e) => this.handlePagination(e)} />
	 	 	 	 	 	 <Pagination.Prev onClick={(e) => this.handlePagination(e)} />{
	 	 	 	 	 	 	 	this.state.pageArray && this.state.pageArray.length &&
	 	 	 	 	 	 	 	this.state.pageArray.map(
	 	 	 	 	 	 	 	 	 (item) => (
	 	 	 	 	 	 	 	 	 	 	<Pagination.Item key={item} onClick={(e) => this.handlePagination(e)}
	 	 	 	 	 	 	 	 	 	 	active={this.state.currentPage == item}>{item}</Pagination.Item>
	 	 	 	 	 	 	 	 	 )
	 	 	 	 	 	 	 	)
	 	 	 	 	 	 }
	 	 	 	 	 	 <Pagination.Next onClick={(e) => this.handlePagination(e)} />
	 	 	 	 	 	 <Pagination.Last onClick={(e) => this.handlePagination(e)} />
	 	 	 	 	</Pagination>
	 	 	 </>
	 	);
}

接下来,打开 App 组件 (src/App.js),导入 bootstrap css 并使用 SimplePagination 组件更新内容,如下所示 -


import './App.css'
import "bootstrap/dist/css/bootstrap.min.css";
import SimplePagination from './Components/SimplePagination'
function App() {
	 	return (
	 	 	 <div className="container">
	 	 	 	 	<div style={{ padding: "10px" }}>
	 	 	 	 	 	 <div>
	 	 	 	 	 	 	 	<SimplePagination />
	 	 	 	 	 	 </div>
	 	 	 	 	</div>
	 	 	 </div>
	 	);
}
export default App;

最后,在浏览器中打开应用程序,检查分页是否正常工作,如下所示 -

总结

React Bootstrap 分页组件提供了必要的组件来渲染简单和复杂的分页设计。