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>
关键细节说明
skip()与limit()的配合:skip(skip):跳过前skip条数据,比如第2页、每页20条时,跳过前20条从第21条开始查询limit(limit):强制返回指定条数的结果,确保每页数据量统一
Promise.all()的优势:同时执行产品查询和总条数统计,比串行执行两个await减少等待时间- 总页数计算:用
Math.ceil()向上取整,比如45个产品、每页20条时,总页数为3页(避免最后5个产品无法展示) - 分页导航优化:仅显示当前页前后2个页码,避免总页数过多时导航栏过长
内容的提问来源于stack exchange,提问作者christian_l30
相关产品推荐
相关产品推荐

