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

如何修复含分类与子分类筛选的分页异常问题?

问题分析与修复方案

核心问题排查

你的分页异常来自以下代码缺陷:

  • 重复定义冲突:全局与DOMContentLoaded回调里重复定义了同名函数(updateProductList、renderProducts)和变量,导致逻辑覆盖、状态混乱
  • 分页计算错误:子分类逻辑里总页数用浮点值比较,分类逻辑里用currentPage * 4判断分页,和每页20条的设定完全不符
  • 重复绑定事件:每次调用更新函数都重新给复选框绑定change事件,触发多次请求导致状态异常
  • 数据显示覆盖:渲染函数最后把总产品数元素改成当前页数量,导致分页判断依赖的总数量丢失

修复后的完整代码

// 全局变量统一声明
const productList = document.querySelector("#products");
const productCountElement = document.querySelector("#product-count");
let currentPage = 1;
const pageElement = document.querySelector("#page-number");
const prevPageButton = document.getElementById("prevPage");
const nextPageButton = document.getElementById("nextPage");
let totalProducts = 0;
const PER_PAGE = 20; // 统一每页数量常量

// 统一产品渲染函数
function renderProducts(products) {
  productList.innerHTML = "";
  let currentRow;
  let counter = 0;
  pageElement.innerHTML = `Page ${currentPage}`;

  products.forEach((product) => {
    if (counter % 4 === 0) {
      currentRow = productList.insertRow();
    }

    const cell = currentRow.insertCell();
    cell.style.width = "200px";
    cell.style.marginRight = "10px";
    
    const productInfo = document.createElement("div");
    productInfo.classList.add("product-info");
    
    const idHeading = document.createElement("h3");
    idHeading.textContent = product.id;
    productInfo.appendChild(idHeading);
    
    const fabricHeading = document.createElement("h6");
    fabricHeading.textContent = product.fabric;
    productInfo.appendChild(fabricHeading);
    
    const designNoHeading = document.createElement("h4");
    designNoHeading.textContent = product.design_no;
    productInfo.appendChild(designNoHeading);
    
    cell.appendChild(productInfo);
    counter++;

    if (counter === 4) {
      currentRow = productList.insertRow();
      counter = 0;
    }
  });

  // 显示当前页数量/总数量
  productCountElement.textContent = `${products.length} / ${totalProducts}`;
}

// 子分类筛选逻辑
function updateSubcategoryProducts() {
  const selectedSubcategoryIds = Array.from(
    document.querySelectorAll(".subcategory-checkbox:checked")
  ).map(checkbox => checkbox.getAttribute("data-subcategory-id"));

  const url = selectedSubcategoryIds.length > 0
    ? `get_products.php?subcategory_ids=${selectedSubcategoryIds.join(",")}&page=${currentPage}`
    : `get_products.php?page=${currentPage}`;

  fetch(url)
    .then(response => response.json())
    .then(data => {
      totalProducts = data.total_count;
      renderProducts(data.products);
      updatePaginationState();
    });
}

// 分类筛选逻辑
function updateCategoryProducts() {
  const selectedCategoryIds = Array.from(
    document.querySelectorAll(".category-checkbox:checked")
  ).map(checkbox => checkbox.getAttribute("data-category-id"));

  const url = selectedCategoryIds.length > 0
    ? `get_product_category.php?category_ids=${selectedCategoryIds.join(",")}&page=${currentPage}`
    : `get_product_category.php?page=${currentPage}`;

  fetch(url)
    .then(response => response.json())
    .then(data => {
      totalProducts = data.total_count;
      renderProducts(data.products);
      updatePaginationState();
    });
}

// 统一分页状态更新
function updatePaginationState() {
  const totalPages = Math.ceil(totalProducts / PER_PAGE);
  nextPageButton.disabled = currentPage >= totalPages;
  prevPageButton.disabled = currentPage <= 1;
}

// 分页按钮事件
prevPageButton.addEventListener("click", () => {
  if (currentPage > 1) {
    currentPage--;
    // 判断当前激活的筛选类型
    const hasCategory = document.querySelector(".category-checkbox:checked");
    const hasSubcategory = document.querySelector(".subcategory-checkbox:checked");
    
    hasCategory ? updateCategoryProducts() : updateSubcategoryProducts();
  }
});

nextPageButton.addEventListener("click", () => {
  const totalPages = Math.ceil(totalProducts / PER_PAGE);
  if (currentPage < totalPages) {
    currentPage++;
    const hasCategory = document.querySelector(".category-checkbox:checked");
    const hasSubcategory = document.querySelector(".subcategory-checkbox:checked");
    
    hasCategory ? updateCategoryProducts() : updateSubcategoryProducts();
  }
});

// 初始化事件绑定(仅绑定一次)
document.querySelectorAll(".subcategory-checkbox").forEach(checkbox => {
  checkbox.addEventListener("change", () => {
    currentPage = 1; // 筛选变更时重置到第一页
    updateSubcategoryProducts();
  });
});

document.querySelectorAll(".category-checkbox").forEach(checkbox => {
  checkbox.addEventListener("change", () => {
    currentPage = 1; // 筛选变更时重置到第一页
    updateCategoryProducts();
  });
});

// 页面加载初始化
document.addEventListener("DOMContentLoaded", updateSubcategoryProducts);

PHP端配套检查

确保你的两个接口做以下处理:

  • 接收page参数,计算offset = (page - 1) * 20,用LIMIT offset, 20获取对应页数据
  • 同时返回筛选后的总产品数(执行不带LIMIT的COUNT查询),保证data.total_count数值正确
  • 处理空筛选参数的情况,返回全部产品

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 00:55:56