在 React 中实现原生分页

Irakli Tchigladze 2022年5月18日
在 React 中实现原生分页

React 是一个用于构建现代单页应用程序的 JavaScript 库。SPA 以其速度和卓越的用户体验而闻名。但是,实现提供出色 UX 的功能需要付出很多努力。

分页是这些功能之一,对于一些包含大量数据的应用程序来说是必不可少的。

无论你的应用程序有多复杂,分页都可以让你确保网站上的页面没有信息过多。分页将使用户能够轻松访问内容。

例如,如果你的博客有很多帖子,用户可能需要一段时间才能找到几年前的特定帖子。当有分页功能并且每个页面都有特定数量的帖子时,这更容易做到。

我们可以在后端或前端进行分页。本文旨在讨论在 React 中原生实现分页功能。

在 React 中实现原生分页

要在 React 中实现原生解决方案,我们需要使用状态。例如,我们需要一个状态变量 currentPage 来存储一个整数来指定应该显示哪些项目批次。

我们还将有一个状态变量来存储每个页面上显示的项目数。我们可以拥有固定数量的项目,而不是将这些信息存储在变量中。

但是,如果我们想改变每页显示的项目数或者让用户改变,最好把它保存在 state 中。最后,我们应该有一个状态变量来存储要显示的项目。

我们来看一个实际的例子:

import "./styles.css";
import { useState } from "react";
export default function App() {
    const [items, setItems] = useState([
        "item 1",
        "item 2",
        "item 3",
        "item 4",
        "item 5",
        "item 6",
        "item 7",
        "item 8",
        "item 9",
        "item 10"
    ]);
    const [currentPage, setCurrentPage] = useState(1);
    const [todosPerPage, setTodosPerPage] = useState(3);
    return (
        <div className="App">
        </div>
    );
}

在此代码示例中,我们导入 useState 挂钩并设置三个状态变量:

  • items 来存储我们需要显示的项目,
  • currentPage 存储需要显示的页面的整数值(默认为 1),以及
  • todosPerPage 存储每页上的项目数。

现在,让我们在代码中添加一点逻辑。

由于我们在每个页面上显示一定数量的项目,并且用户可以在页面之间切换,因此我们需要弄清楚需要显示哪些项目。我们有十个项目,每页有三个项目,所以我们将有四页。

第一页将显示第一个、第二个和第三个项目,依此类推。我们可以硬编码应该为每个页面显示哪些项目,但是开发一个可以处理任意数量项目的系统要明智得多。

我们来看看逻辑:

const [currentPage, setCurrentPage] = useState(1);
const [todosPerPage, setTodosPerPage] = useState(3);
const lastTodoInView = currentPage * todosPerPage;
const firstTodoInView = lastTodoInView - todosPerPage;

lastTodoInViewfirstTodoinView 这两个变量表示数组中的索引,这应该是在特定页面上显示项目的边界。例如,对于第一页,假设 todosPerPage 设置为三,边界将是:

最后一个:1 (currentPage) * 3 (todosPerPage) = 3

第一个:3 (lastTodoInView) - 3 (todosPerPage) = 0

请注意,在 JavaScript 中,数组的第一项索引为 0,因此要显示在第一页上的项将具有 0、1 和 2 索引,直到它们达到 3。最后一个数组索引不包含在内,因为如何 .slice() 方法是设计好的,所以我们的页面不会包含索引 3 上的项目。

接下来,我们可以使用 .slice() 方法来提取每个页面上显示的特定值。

const todosForDisplay = items.slice(firstTodoInView, lastTodoInView);

这个方法有两个参数,数组项的开始和结束索引。起始索引是包含的,这意味着如果第一个参数为 0,则一旦执行该方法,新返回的数组将包含第一项。

结束索引不包含在内,这意味着如果第二个参数为 3,则返回的数组将在索引 2 处停止。

然后,我们可以创建一个变量来存储从切片数组生成的所有 JSX 元素。

const renderItems = todosForDisplay.map((todo, index) => {
    return <li key={index}>{todo}</li>;
});

建议将 key 属性设置为唯一值,以便 React 可以在内部跟踪各个节点。

稍后,我们将添加代码以允许用户更改 currentPage 变量,或者简单地说,从一个页面转到另一个页面。我们还可以添加更新每个页面上显示的项目数量的功能,一切都会正常工作。

接下来,我们必须生成一个页码数组。随着数组中项目数量的增加,页数也应该增加。

例如,目前,我们的数组有 10 个项目和 4 个页面来显示它们。如果我们再添加 5 个项目,我们需要计算要显示它们的页面数。

以下是计算显示所有项目所需的页数的逻辑:

const pageNumbers = [];
for (let n = 1; n <= Math.ceil(items.length / todosPerPage); n++) {
    pageNumbers.push(n);
}

在这里,我们生成了一个简单的 for 循环。我们从初始值 1 开始,并将其添加到 pageNumbers 数组中。

我们添加越来越多的页面,直到有足够的页面来显示每个项目。然后我们必须生成要在应用程序中显示的实际页码。

为此,我们将在 pageNumbers 数组上使用 .map() 方法。让我们看一下代码:

const renderPageNumbers = pageNumbers.map((number, index) => {
    return <li key={index}>{number}</li>;
});

这将生成与页码对应的所有 JSX 元素。我们必须创建一个事件处理程序以允许用户从一个页面移动。

这很容易实现,因为 useState() 钩子提供了一个简单的更新函数来更新值。我们要处理点击事件,事件处理函数可以很简单:

const renderPageNumbers = pageNumbers.map((number, index) => {
    return <li onClick={() => setCurrentPage(number)} key={index}>
        {number}
    </li>
});

最后,我们简单的分页系统就完成了。你可以查看 CodeSandbox 上的演示,了解所有内容如何组合在一起。

Irakli Tchigladze avatar Irakli Tchigladze avatar

Irakli is a writer who loves computers and helping people solve their technical problems. He lives in Georgia and enjoys spending time with animals.

LinkedIn