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

JavaScript多类别商品筛选功能实现问题求助

多类别商品筛选功能修复方案

需求回顾

  • 默认状态下所有商品卡片均激活显示
  • 点击按钮可切换对应类别的显示/隐藏状态
  • 选中多个按钮时,仅展示同时包含所有选中类别的商品卡片

修复后的完整代码

let products = {
  data: [
    {
      productName: "Fantasy",
      heart: "./icons/heart.svg",
      heartCount: 2547,
      category: "Salmon, Shrimp",
      content:
        "Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
      picture: "./images/pexels-diego-pontes-901015-2323391.jpg",
    },
    {
      productName: "Spring",
      heart: "./icons/heart.svg",
      heartCount: 2547,
      category: "Veggie",
      content:
        "Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
      picture: "./images/pexels-pixabay-357756.jpg",
    },
    {
      productName: "Rainbow",
      heart: "./icons/heart.svg",
      heartCount: 2547,
      category: "Salmon, Tuna, Unagi",
      content:
        "Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
      picture: "./images/pexels-freestockpro-3147493.jpg",
    },
    {
      productName: "Unique",
      heart: "./icons/heart.svg",
      heartCount: 2547,
      category: "Salmon, Tuna, Unagi, Shrimp",
      content:
        "Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
      picture: "./images/pexels-photo-248444.webp",
    },
    {
      productName: "Perfection",
      heart: "./icons/heart.svg",
      heartCount: 2547,
      category: "Salmon",
      content:
        "Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
      picture: "./images/pexels-isabella-mendes-107313-858501.jpg",
    },
    {
      productName: "Style",
      heart: "./icons/heart.svg",
      heartCount: 2547,
      category: "Salmon, Tuna, Unagi, Shrimp",
      content:
        "Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
      picture: "./images/pexels-rajesh-tp-749235-2098143.jpg",
    },
    {
      productName: "Dreamy",
      heart: "./icons/heart.svg",
      heartCount: 2547,
      category: "Salmon",
      content:
        "Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
      picture: "./images/pexels-viniciusbenedit-3620705.jpg",
    },
    {
      productName: "Spicy",
      heart: "./icons/heart.svg",
      heartCount: 2547,
      category: "Shrimp",
      content:
        "Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
      picture: "./images/pexels-catscoming-699544.jpg",
    },
  ],
};

// 生成商品卡片
for (let i of products.data) {
  let card = document.createElement("div");
  card.classList.add("card");

  // 图片容器
  let imgContainer = document.createElement("div");
  imgContainer.classList.add("image-container");
  let image = document.createElement("img");
  image.classList.add("product-img");
  image.setAttribute("src", i.picture);
  imgContainer.appendChild(image);
  card.appendChild(imgContainer);
  document.getElementById("products").appendChild(card);
  
  // 存储卡片的类别数组(预处理,避免重复解析)
  card.dataset.categories = JSON.stringify(
    i.category.split(",").map(cat => cat.trim())
  );

  image.addEventListener("error", () => {
    image.style.display = "none";
    image.parentNode.style.backgroundColor = "#d9d9d9";
  });

  // 内容区域
  let content = document.createElement("div");
  content.classList.add("content");
  card.appendChild(content);

  // 标题和点赞区
  let contentHead = document.createElement("div");
  contentHead.classList.add("contentHead");
  let productTitle = document.createElement("h2");
  productTitle.classList.add("productTitle");
  productTitle.innerText = i.productName;

  let likesSection = document.createElement("div");
  likesSection.classList.add("likesSection");
  let likesIcon = document.createElement("img");
  likesIcon.setAttribute("src", "./icons/heart.svg");
  likesIcon.classList.add("likesIcon");
  let likesCount = document.createElement("p");
  likesCount.classList.add("likeCount");
  likesCount.innerText = i.heartCount;

  content.appendChild(contentHead);
  contentHead.appendChild(productTitle);
  contentHead.appendChild(likesSection);
  likesSection.appendChild(likesIcon);
  likesSection.appendChild(likesCount);

  likesIcon.addEventListener("error", () => {
    likesIcon.setAttribute(
      "src",
      "https://upload.wikimedia.org/wikipedia/commons/f/f1/Heart_coraz%C3%B3n.svg"
    );
  });

  // 分隔线
  let line = document.createElement("hr");
  line.classList.add("product-line");
  content.appendChild(line);

  // 类别显示
  let itemCategory = document.createElement("p");
  itemCategory.classList.add("item-category");
  itemCategory.innerText = i.category;
  content.appendChild(itemCategory);

  // 描述
  let itemDescription = document.createElement("p");
  itemDescription.classList.add("itemDescription");
  itemDescription.innerText = i.content;
  content.appendChild(itemDescription);

  // 查看更多
  let readMore = document.createElement("p");
  readMore.classList.add("readMore");
  readMore.innerText = "Read more >>>";
  content.appendChild(readMore);
}

// 筛选逻辑
let buttons = document.querySelectorAll(".category-button");
let cards = document.querySelectorAll(".card");
let selectedCategories = new Set(); // 用Set存储选中的类别,自动去重

// 统一的筛选函数
function filterProducts() {
  cards.forEach(card => {
    const cardCategories = JSON.parse(card.dataset.categories);
    
    // 无选中类别时显示所有卡片
    if (selectedCategories.size === 0) {
      card.classList.remove("inactive-card");
      return;
    }

    // 检查卡片是否包含所有选中的类别
    const hasAllCategories = [...selectedCategories].every(cat => 
      cardCategories.includes(cat)
    );

    if (hasAllCategories) {
      card.classList.remove("inactive-card");
    } else {
      card.classList.add("inactive-card");
    }
  });
}

// 绑定按钮点击事件
buttons.forEach(button => {
  button.addEventListener("click", () => {
    const category = button.innerText.trim();
    button.classList.toggle("active-button");

    // 更新选中类别集合
    if (button.classList.contains("active-button")) {
      selectedCategories.add(category);
    } else {
      selectedCategories.delete(category);
    }

    // 执行筛选
    filterProducts();
  });
});

关键修改说明

  1. 预处理卡片类别:生成卡片时,将类别解析为数组并存储在dataset.categories中,避免每次筛选重复解析字符串,提升性能。
  2. 用Set管理选中类别:自动去重,简化添加/删除操作。
  3. 重构筛选逻辑:
    • 无选中按钮时直接显示所有卡片
    • 使用every()方法检查卡片是否包含所有选中类别,完全匹配需求中的“多类别交集筛选”
  4. 避免重复绑定事件:移除原代码中嵌套的按钮事件绑定逻辑,改为单次绑定,避免重复触发问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 08:55:55