如何使用React实现前台分页

1,650 阅读6分钟

使用React实现前台分页

为了改善用户体验,让网站的导航更容易,大多数网站不会在一个网页上显示所有获取的数据。大多数开发者实现了分页,使数据可以在一系列的页面上显示。用户可以通过点击一个按钮轻松地从一个页面导航到另一个页面。

分页可以在服务器端或客户端实现。在服务器端,客户端按组请求数据,例如,客户端可以从API或数据库中请求一个前十项的列表。然后,当用户点击网页上的下一个按钮时,就会从服务器上请求另一组数据。

在这篇文章中,我们将看一下客户端分页。这就是客户端获取所有的数据并将其存储在一个状态中。然后,分页可以在前端实现。我们将使用React(一个用于构建用户界面的JavaScript库),我们将使用Tailwind CSS来设计我们的网页。

前提条件

为了能够跟上进度,读者应该具备。

  • 基本的React知识。
  • 安装了Node.js。
  • 对Fetch API的基本了解。
  • 一个代码编辑器和一个浏览器。

目标

这篇文章将使读者能够。

  • 在React中实现前端分页。
  • 使用React类组件。
  • 使用Tailwind CSS对网页进行样式设计。
  • 在获取数据时实现一个加载状态。

设置我们的项目

要开始,打开终端导航到你要创建项目的地方,然后运行以下命令。

npx create-react-app react-tailwind-pagination

上述命令将创建你的React应用程序。

运行以下命令,cd 到你的项目,并在你的代码编辑器中打开它,在这种情况下,我们使用VS Code。

cd react-tailwind-pagination

code .

安装依赖项

在这个项目中,我们将只需要一个依赖项。

使用下面的命令来安装它。

npm i react-loader-spinner

上面的命令安装了一个包,我们将用它来显示从API中获取数据时的加载动画。

开始使用分页功能

打开App.js 文件,用下面提供的代码修改。

import React, { Component } from "react";
import Loader from "react-loader-spinner"

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      currentPage: 1,
      posts: [], 
      loading: null,
      postsPerPage: 5
    };
  }
  render() {
   

    return (
      <div className="w-4/5 mx-auto">

        <h2 className="text-2xl text-center font-bold">React Pagination Using Class Components and Tailwind CSS</h2>
        <hr />
      </div>
    );
  }
}

export default App;

代码解释

在上面的代码中,我们已经定义了五个初始状态,如下所述。

  • currentPage - 这个状态将保持客户当前所处的页面的值。默认值是第1页。当用户从一个页面导航到另一个页面时,这个状态将被持续更新。
  • posts - 这个状态将是将从API中获取的数据。它的初始状态是一个空数组。
  • loading - 这个状态将保持加载状态的值。它只能取两个值, 或 。如果加载状态为真,将显示一个加载旋钮。如果它是假的,实际的内容,即帖子,将被显示。true false
  • postsPerPage - 这个状态将保持每页显示的帖子数量。这可以根据个人的需要来调整。

获取数据

为了获取数据,在constructor() 方法下粘贴以下代码。

componentDidMount() { 
    this.setState({loading: true})
    fetch('https://jsonplaceholder.typicode.com/posts')
    .then((res) => res.json())
    .then(data => {
        this.setState({ posts: data });
        this.setState({loading: false})
    })
  }

代码解释

在上面的代码中,我们是在组件安装后获取数据的。我们通过使用componentDidMount() 方法来实现这一点。

当组件挂载时,我们通过使用setState() 方法将加载状态设置为真,以更新状态值。

然后我们使用fetch API从jsonplaceholder API中获取数据。在获取数据后,我们使用this.setState({ posts: data }) 将其存储在帖子状态中。然后,加载状态被设置为false

在网页上显示数据

为了在网页上显示数据,我们将使用map() 方法。

<hr /> 标签下面的return() 部分中粘贴以下代码。

{
    this.state.loading === true
    ? 
    <div className="w-full h-screen flex items-center justify-center">
        <Loader
            type="BallTriangle"
            color="#00BFFF"
            height={100}
            width={100}
        />
    </div>
    :          
    posts.map((post, id) => (
    <div key={id} className="border-2 border-blue-500 rounded m-4 p-4">
        <div className="text-lg font-bold">{post.title}</div>
        <div className="mt-2">{post.body}</div>
    </div>
    ))
}

代码解释

在上面的代码中,我们正在使用三元操作符来有条件地渲染我们的帖子。如果加载状态是true ,我们正在渲染一个来自react-loader-spinner 包的旋转器,显示数据仍在获取中。如果加载状态是false ,我们就会渲染帖子。

实现分页

要实现分页,请在下面的代码中粘贴render() 方法。

const indexOfLastPost = this.state.currentPage * this.state.postsPerPage;

const indexOfFirstPost = indexOfLastPost - this.state.postsPerPage;

const currentPosts = this.state.posts.slice(indexOfFirstPost, indexOfLastPost);

代码解释

我们使用上面的代码来获取currentPosts ,即我们想在某个页面上显示的帖子。为了得到这个,我们需要计算indexOfLastPost ,即某页的最后一篇文章和indexOfFirstPost ,即某页的第一篇文章。

然后我们使用 slice()数组方法来设置我们想在某个页面上显示的帖子。为了只显示currentPosts() ,到我们渲染帖子的部分,设置map() 方法在currentPosts 数组上循环,如下所示。

currentPosts.map((post, id) => (
    <div key={id} className="border-2 border-blue-500 rounded m-4 p-4">
        <div className="text-lg font-bold">{post.title}</div>
        <div className="mt-2">{post.body}</div>
    </div>
))

实现页码

我们现在需要实现用户将点击的页码,以导航到某个页面。在render() 方法部分,添加以下几行代码。

const pageNumbers = []

for (let i = 1; i <= Math.ceil(this.state.posts.length / this.state.postsPerPage); i++) {
    pageNumbers.push(i);
}

在上面的代码中,我们创建了一个常数pageNumbers ,它是一个数组,将用于保存页数。然后,我们使用一个for 循环来循环查看(posts.length / postsPerPage) 的商数。

posts.length 是帖子的总数,postsPerPage 是每页的帖子数。然后我们把从for 循环中得到的值推到pageNumbers 数组中。为了显示pageNumbers 中的值,粘贴下面的代码;-它将呈现帖子。

<div className="w-full flex justify-around">
          {
            pageNumbers.map((pageNum, index) => (
              <span key={index} 
                className={pageNum === this.state.currentPage 
                ? "cursor-pointer flex items-center justify-center w-12 h-12 border-2 rounded-full bg-blue-500 text-white" 
                : "cursor-pointer flex items-center justify-center w-12 h-12 border-2 rounded-full"} 
              
                onClick={() => {setPage(pageNum)}}>

                {pageNum}

              </span>
            ))
          }
        </div>

在上面的代码中,我们使用map() 方法来循环浏览pageNumbers 数组并显示页码。我们还使用条件渲染来检查页码是否等于当前页码。如果是的话,我们将以不同的方式进行样式设计,以确保用户知道他们在哪一页。

随着对某个页码的点击,我们正在调用setPage() 方法,我们使用该方法来帮助用户从一个页面导航到另一个。

setPage() 方法的代码提供如下。

const setPage = (pageNum) => {
    this.setState({currentPage: pageNum})
}

该函数接收了pageNum 作为参数,并使用它来更新当前的页面状态。在currentPage 状态被更新后,新的值indexOfLastPost,indexOfFirstPostcurrentPosts 被计算出来,页面内容立即被更新。

分页的完整代码

import React, { Component } from "react";
import Loader from "react-loader-spinner"

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      currentPage: 1, //Holds the value for the current page
      posts: [], //Array where the data is stored
      loading: null, //Holds the value for the loading state.. can either be true or false
      postsPerPage: 5 //Holds the value for the number of posts per page. You can adjust to suit your needs
    };
  }

  //Fetch data on component mount
  componentDidMount() { 
    this.setState({loading: true})
    fetch('https://jsonplaceholder.typicode.com/posts')
    .then((res) => res.json())
    .then(data => {
        this.setState({ posts: data });
        this.setState({loading: false})
    })
  }

  render() {
    //Get currentPosts
    const indexOfLastPost = this.state.currentPage * this.state.postsPerPage;
    const indexOfFirstPost = indexOfLastPost - this.state.postsPerPage;
    const currentPosts = this.state.posts.slice(indexOfFirstPost, indexOfLastPost);

    //Implement page numbers
    const pageNumbers = []

    for (let i = 1; i <= Math.ceil(this.state.posts.length / this.state.postsPerPage); i++) {
      pageNumbers.push(i);
    }

    //Set current page
    const setPage = (pageNum) => {
      this.setState({currentPage: pageNum})
    }

    return (
      <div className="w-4/5 mx-auto">

        <h2 className="text-2xl text-center font-bold">React Pagination Using Class Components and Tailwind CSS</h2>
        <hr />

        {
          this.state.loading === true
            ? <div className="w-full h-screen flex items-center justify-center">
                <Loader
                  type="BallTriangle"
                  color="#00BFFF"
                  height={100}
                  width={100}
                />
            </div>
          :          
          currentPosts.map((post, id) => (
            <div key={id} className="border-2 border-blue-500 rounded m-4 p-4">
              <div className="text-lg font-bold">{post.title}</div>
              <div className="mt-2">{post.body}</div>
            </div>
          ))
        }

        <div className="w-full flex justify-around">
          {
            pageNumbers.map((pageNum, index) => (
              <span key={index} className={pageNum === this.state.currentPage ? "cursor-pointer flex items-center justify-center w-12 h-12 border-2 rounded-full bg-blue-500 text-white" : "cursor-pointer flex items-center justify-center w-12 h-12 border-2 rounded-full"} onClick={() => {setPage(pageNum)}}>
                {pageNum}
              </span>
            ))
          }
        </div>
        

        <div></div>
      </div>
    );
  }
}

export default App;

运行该项目

要运行该项目,请打开你的终端并运行以下命令。

npm start

这将启动一个本地开发服务器。转到127.0.0.1:3000 ,你就可以查看你的网页了。

总结

这是在react中实现前端分页的一种方法。你可以继续修改代码,使之最适合你的需要。你也可以在你的项目中应用这段代码进行练习。

希望你觉得这个教程对你有帮助。