You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用React与Node.js实现分页?MongoDB博客分页工具求推荐

实现React+Node+MongoDB博客分页的完整方案

我来给你详细拆解这个分页实现的步骤,从后端接口到前端交互,还有好用的工具库推荐,一步到位~

一、后端(Node.js + MongoDB)实现分页逻辑

MongoDB本身就提供了实现分页的核心方法:skip() 和 limit(),配合Express框架就能轻松搞定分页接口。核心思路是:接收前端传的页码和每页条数,计算需要跳过的文章数量,再查询对应范围的文章,同时返回总条数和总页数给前端做交互判断。

原生实现代码示例

// 后端路由文件(比如routes/posts.js)
const express = require('express');
const router = express.Router();
const Post = require('../models/Post'); // 你的文章Model

router.get('/', async (req, res) => {
  try {
    // 获取前端传的分页参数,默认第1页、每页5条
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 5;
    
    // 计算需要跳过的文章数:(当前页-1)*每页条数
    const skip = (page - 1) * limit;
    
    // 查询当前页的文章(按创建时间倒序),同时获取总文章数
    const posts = await Post.find().sort({ createdAt: -1 }).skip(skip).limit(limit);
    const totalPosts = await Post.countDocuments();
    
    // 计算总页数
    const totalPages = Math.ceil(totalPosts / limit);
    
    res.status(200).json({
      posts,
      pagination: {
        currentPage: page,
        totalPages,
        totalPosts,
        limit
      }
    });
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
});

module.exports = router;

注意:skip()在数据量极大时可能有性能问题,如果后期文章量特别大,可以考虑基于最后一篇文章的_id或时间戳做分页,避免跳过大量数据。

二、前端(React.js)实现分页交互

前端需要维护当前页码状态,根据页码请求对应数据,再渲染分页控件(上一页、下一页、页码按钮)来切换页码。

自定义分页组件实现

// 前端博客首页组件(比如Home.jsx)
import { useState, useEffect } from 'react';

const Home = () => {
  const [posts, setPosts] = useState([]);
  const [pagination, setPagination] = useState({});
  const [currentPage, setCurrentPage] = useState(1);

  // 页码变化时重新请求数据
  useEffect(() => {
    const fetchPosts = async () => {
      try {
        const res = await fetch(`/api/posts?page=${currentPage}&limit=5`);
        const data = await res.json();
        setPosts(data.posts);
        setPagination(data.pagination);
        // 切换页码后滚动到页面顶部
        window.scrollTo({ top: 0, behavior: 'smooth' });
      } catch (error) {
        console.error('获取文章失败:', error);
      }
    };
    fetchPosts();
  }, [currentPage]);

  // 处理页码切换逻辑
  const handlePageChange = (newPage) => {
    if (newPage >= 1 && newPage <= pagination.totalPages) {
      setCurrentPage(newPage);
    }
  };

  return (
    <div className="home-container">
      <h1>我的博客</h1>
      {/* 文章列表 */}
      <div className="posts-list">
        {posts.map(post => (
          <div key={post._id} className="post-card">
            <h2>{post.title}</h2>
            <p>{post.excerpt}</p>
            {/* 其他文章内容 */}
          </div>
        ))}
      </div>

      {/* 分页控件(仅当总页数>1时显示) */}
      {pagination.totalPages > 1 && (
        <div className="pagination">
          <button 
            onClick={() => handlePageChange(currentPage - 1)}
            disabled={currentPage === 1}
          >
            上一页
          </button>
          
          {/* 渲染所有页码按钮 */}
          {Array.from({ length: pagination.totalPages }, (_, i) => i + 1).map(page => (
            <button
              key={page}
              onClick={() => handlePageChange(page)}
              className={currentPage === page ? 'active-page' : ''}
            >
              {page}
            </button>
          ))}
          
          <button 
            onClick={() => handlePageChange(currentPage + 1)}
            disabled={currentPage === pagination.totalPages}
          >
            下一页
          </button>
        </div>
      )}
    </div>
  );
};

export default Home;

三、好用的工具库推荐

如果不想自己写重复逻辑,这些工具库能帮你省不少事:

后端:mongoose-paginate-v2

这个库封装了MongoDB的分页逻辑,不用手动写skip()、limit()和计数查询,直接给Model添加分页方法:

// 安装:npm install mongoose-paginate-v2
const mongoose = require('mongoose');
const mongoosePaginate = require('mongoose-paginate-v2');

const postSchema = new mongoose.Schema({
  title: String,
  content: String,
  createdAt: { type: Date, default: Date.now }
});

// 给Schema添加分页插件
postSchema.plugin(mongoosePaginate);
const Post = mongoose.model('Post', postSchema);

// 路由中使用
router.get('/', async (req, res) => {
  const options = {
    page: parseInt(req.query.page) || 1,
    limit: parseInt(req.query.limit) || 5,
    sort: { createdAt: -1 } // 按创建时间倒序
  };

  try {
    const result = await Post.paginate({}, options);
    res.status(200).json({
      posts: result.docs,
      pagination: {
        currentPage: result.page,
        totalPages: result.totalPages,
        totalPosts: result.totalDocs,
        limit: result.limit
      }
    });
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
});

前端:react-paginate

这个组件封装了分页的UI和交互逻辑,不用自己写按钮切换逻辑,直接配置参数即可使用:

// 安装:npm install react-paginate
import { useState, useEffect } from 'react';
import ReactPaginate from 'react-paginate';

const Home = () => {
  const [posts, setPosts] = useState([]);
  const [pagination, setPagination] = useState({});
  const [currentPage, setCurrentPage] = useState(0); // react-paginate从0开始计数

  useEffect(() => {
    const fetchPosts = async () => {
      // 注意转成后端需要的从1开始的页码
      const res = await fetch(`/api/posts?page=${currentPage + 1}&limit=5`);
      const data = await res.json();
      setPosts(data.posts);
      setPagination(data.pagination);
      window.scrollTo({ top: 0, behavior: 'smooth' });
    };
    fetchPosts();
  }, [currentPage]);

  const handlePageChange = (selected) => {
    setCurrentPage(selected.selected);
  };

  return (
    <div className="home-container">
      {/* 文章列表部分和之前一致 */}
      <div className="posts-list">
        {posts.map(post => (
          <div key={post._id} className="post-card">
            <h2>{post.title}</h2>
            <p>{post.excerpt}</p>
          </div>
        ))}
      </div>

      {/* 使用react-paginate组件 */}
      {pagination.totalPages > 1 && (
        <ReactPaginate
          breakLabel="..."
          nextLabel="下一页 →"
          onPageChange={handlePageChange}
          pageRangeDisplayed={3}
          pageCount={pagination.totalPages}
          previousLabel="← 上一页"
          renderOnZeroPageCount={null}
          containerClassName="pagination"
          activeClassName="active-page"
        />
      )}
    </div>
  );
};

export default Home;

内容的提问来源于stack exchange,提问作者Mahma Deva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:22:31