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

Node.js+Mongoose+EJS商城产品分页加载实现技术问询

商城分页加载产品实现(Node.js + Mongoose + EJS)

核心逻辑

分页的本质是按页码截取数据库中的数据片段:

  • 前端通过URL参数(如?page=2&limit=20)告知后端目标页码和每页数据量
  • 后端用Mongoose的skip()(跳过前置条目)和limit()(限制返回条数)查询对应数据
  • 同步计算总页数,传给前端生成分页导航
  • 点击分页按钮时,前端修改URL参数并重新请求页面

后端实现(Node.js + Mongoose)

假设已有Product模型,以下是分页查询的路由代码:

const express = require('express');
const router = express.Router();
const Product = require('../models/Product'); // 你的产品模型文件路径

router.get('/products', async (req, res) => {
  try {
    // 解析URL参数,设置默认值(页码默认1,每页默认20条)
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 20;

    // 计算需要跳过的条目数:(当前页-1)*每页数量
    const skip = (page - 1) * limit;

    // 并行执行查询:获取当前页产品 + 统计总产品数,提升效率
    const [products, totalProducts] = await Promise.all([
      Product.find().skip(skip).limit(limit).sort({ createdAt: -1 }), // 按创建时间倒序排列
      Product.countDocuments() // 获取数据库中产品总条数
    ]);

    // 计算总页数,向上取整避免遗漏最后一页的少量数据
    const totalPages = Math.ceil(totalProducts / limit);

    // 将数据传入EJS模板渲染
    res.render('products', {
      products,
      currentPage: page,
      totalPages,
      limit
    });
  } catch (err) {
    console.error(err);
    res.status(500).send('服务器出错');
  }
});

module.exports = router;

前端实现(EJS)

在products.ejs模板中,先渲染产品列表,再生成分页导航:

产品列表渲染

<div class="products-grid">
  <% products.forEach(product => { %>
    <div class="product-card">
      <h3><%= product.name %></h3>
      <p>价格:<%= product.price %>元</p>
      <!-- 按需添加其他产品信息(图片、描述等) -->
    </div>
  <% }) %>
</div>

分页导航按钮

<div class="pagination">
  <!-- 上一页按钮:当前页为第一页时禁用 -->
  <a href="/products?page=<%= currentPage - 1 %>&limit=<%= limit %>" 
     <%= currentPage === 1 ? 'class="disabled"' : '' %>>
    上一页
  </a>

  <!-- 页码按钮:只显示当前页前后2个页码,避免页码过多 -->
  <% for (let i = Math.max(1, currentPage - 2); i <= Math.min(totalPages, currentPage + 2); i++) { %>
    <a href="/products?page=<%= i %>&limit=<%= limit %>" 
       <%= i === currentPage ? 'class="active"' : '' %>>
      <%= i %>
    </a>
  <% } %>

  <!-- 下一页按钮:当前页为最后一页时禁用 -->
  <a href="/products?page=<%= currentPage + 1 %>&limit=<%= limit %>" 
     <%= currentPage === totalPages ? 'class="disabled"' : '' %>>
    下一页
  </a>
</div>

关键细节说明

  1. skip()与limit()的配合:
    • skip(skip):跳过前skip条数据,比如第2页、每页20条时,跳过前20条从第21条开始查询
    • limit(limit):强制返回指定条数的结果,确保每页数据量统一
  2. Promise.all()的优势:同时执行产品查询和总条数统计,比串行执行两个await减少等待时间
  3. 总页数计算:用Math.ceil()向上取整,比如45个产品、每页20条时,总页数为3页(避免最后5个产品无法展示)
  4. 分页导航优化:仅显示当前页前后2个页码,避免总页数过多时导航栏过长

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 23:45:42