ReactJS - 分頁



React 透過第三方 UI 元件庫提供分頁元件。React 社群提供了大量的 UI/UX 元件,很難選擇適合我們需求的庫。Bootstrap UI 庫是開發人員的流行選擇之一,並且被廣泛使用。React Bootstrap(https://react-bootstrap.github.io/)幾乎移植了所有 Bootstrap UI 元件,並且對Pagination元件也提供了最佳支援。

讓我們在本節中學習如何在 Web 應用中使用來自 react-bootstrap 庫的Pagination元件。

分頁元件

Pagination元件允許開發人員在 Web 應用中建立具有 Bootstrap 設計的簡單分頁。分頁元件接受以下元件。

  • Pagination.Item

  • Pagination.First

  • Pagination.Last

  • Pagination.Previous

  • Pagination.Next

Pagination元件接受少量 props 來自定義分頁元件,如下所示:

  • size (sm | lg)

  • 設定分頁按鈕的大小

  • bsPrefix (string)

  • 能夠更改底層元件的 CSS

Pagination.Item元件接受少量 props 來自定義分頁元件,如下所示:

  • active (boolean)

  • 將專案設定為活動專案,並且不渲染標籤。

  • activeLabel (string)

  • 指示分頁專案狀態的標籤

  • disabled (boolean)

  • 停用分頁專案

  • href (string)

  • 分頁專案的連結

  • onClick (function)

  • 單擊事件觸發時呼叫的回撥函式

應用Pagination元件

首先,建立一個新的 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;

接下來,在 public 資料夾下建立一個檔案 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@tutorialspoint.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;

最後,在瀏覽器中開啟應用程式,並檢查分頁是否正常工作,如下所示:

Pagination

總結

React Bootstrap 分頁元件提供了必要的元件來呈現簡單和複雜的分頁設計。

廣告