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

原生JS实现点击按钮切换单条菜单内容的技术求助

问题解决:动态菜单按钮切换显示对应内容

问题分析

当前代码存在两个核心问题:

  • 页面加载时直接渲染全部菜单元素,不符合默认仅显示第一个元素的需求
  • 点击按钮时,data-id获取的是字符串类型,而菜单对象的id是数字类型,全等判断===导致匹配失败,无法筛选出对应元素

修复方案

1. 页面加载默认显示第一个元素

修改DOMContentLoaded事件中的调用,仅传入包含第一个菜单元素的数组:

window.addEventListener("DOMContentLoaded", function () {
  displayMenuItems([menu[0]]);
  displayMenuButtons();
});

2. 修复按钮点击的元素匹配逻辑

将data-id转换为数字类型后再匹配,同时利用id唯一性,使用find方法替代filter(直接返回单个匹配对象,更高效):

filterBtns.forEach(function(btn){
  btn.addEventListener("click", function(e){
    const categoryId = Number(e.currentTarget.dataset.id);
    const targetItem = menu.find(function(menuItem){
      return menuItem.id === categoryId;
    });
    displayMenuItems(targetItem ? [targetItem] : []);
  })
})

完整修改后的index.js代码

const menu = [
  {
    id: 1,
    title: "buttermilk pancakes",
    category: "breakfast",
    price: 15.99,
    img: "./images/item-1.jpeg",
    desc: `I'm baby woke mlkshk wolf bitters live-edge blue bottle, hammock freegan copper mug whatever cold-pressed `,
  },
  {
    id: 2,
    title: "diner double",
    category: "lunch",
    price: 13.99,
    img: "./images/item-2.jpeg",
    desc: `vaporware iPhone mumblecore selvage raw denim slow-carb leggings gochujang helvetica man braid jianbing. Marfa thundercats `,
  },
  {
    id: 3,
    title: "godzilla milkshake",
    category: "shakes",
    price: 6.99,
    img: "./images/item-3.jpeg",
    desc: `ombucha chillwave fanny pack 3 wolf moon street art photo booth before they sold out organic viral.`,
  },
  {
    id: 4,
    title: "country delight",
    category: "breakfast",
    price: 20.99,
    img: "./images/item-4.jpeg",
    desc: `Shabby chic keffiyeh neutra snackwave pork belly shoreditch. Prism austin mlkshk truffaut, `,
  },
  {
    id: 5,
    title: "egg attack",
    category: "lunch",
    price: 22.99,
    img: "./images/item-5.jpeg",
    desc: `franzen vegan pabst bicycle rights kickstarter pinterest meditation farm-to-table 90's pop-up `,
  },
  {
    id: 6,
    title: "oreo dream",
    category: "shakes",
    price: 18.99,
    img: "./images/item-6.jpeg",
    desc: `Portland chicharrones ethical edison bulb, palo santo craft beer chia heirloom iPhone everyday`,
  },
  {
    id: 7,
    title: "bacon overflow",
    category: "breakfast",
    price: 8.99,
    img: "./images/item-7.jpeg",
    desc: `carry jianbing normcore freegan. Viral single-origin coffee live-edge, pork belly cloud bread iceland put a bird `,
  },
  {
    id: 8,
    title: "american classic",
    category: "lunch",
    price: 12.99,
    img: "./images/item-8.jpeg",
    desc: `on it tumblr kickstarter thundercats migas everyday carry squid palo santo leggings. Food truck truffaut  `,
  },
  {
    id: 9,
    title: "quarantine buddy",
    category: "shakes",
    price: 16.99,
    img: "./images/item-9.jpeg",
    desc: `skateboard fam synth authentic semiotics. Live-edge lyft af, edison bulb yuccie crucifix microdosing.`,
  },
  {
    id: 10,
    title: "steak dinner",
    category: "dinner",
    price: 39.99,
    img: "./images/item-10.jpeg",
    desc: `skateboard fam synth authentic semiotics. Live-edge lyft af, edison bulb yuccie crucifix microdosing.`,
  },
];

const sectionCenter = document.querySelector(".section-center");
const container = document.querySelector(".btn-container");

window.addEventListener("DOMContentLoaded", function () {
  // 默认仅显示第一个菜单元素
  displayMenuItems([menu[0]]);
  displayMenuButtons();
});

function displayMenuItems(menuItems) {
  let displayMenu = menuItems.map(function (item) {
    return `<article class="menu-item">
          <img src=${item.img} class="photo" alt=${item.title} />
          <div class="item-info">
            <header>
              <h4>${item.title}</h4>
              <h4 class="price">$${item.price}</h4>
            </header>
            <p class="item-text">
              ${item.desc}
            </p>
          </div>
        </article>`;
  });
  displayMenu = displayMenu.join("");

  sectionCenter.innerHTML = displayMenu;
}

function displayMenuButtons(){
  const btns = menu.map(function(menuItem){
    return `<button class="filter-btn" type="button" data-id=${menuItem.id}>${menuItem.title}</button>`;
  })
  .join("");
  container.innerHTML = btns;
  
  const filterBtns = container.querySelectorAll(".filter-btn");

  filterBtns.forEach(function(btn){
    btn.addEventListener("click", function(e){
      // 将字符串类型的data-id转换为数字
      const categoryId = Number(e.currentTarget.dataset.id);
      // 查找对应id的菜单元素
      const targetItem = menu.find(menuItem => menuItem.id === categoryId);
      // 渲染找到的元素(包装为数组)
      displayMenuItems(targetItem ? [targetItem] : []);
    })
  })
}

说明

  • 页面加载时,通过[menu[0]]将第一个元素包装为数组传入渲染函数,实现默认只显示第一个内容
  • 点击按钮时,把获取到的data-id转为数字,使用find方法精准匹配唯一的菜单对象,再包装为数组传入渲染函数,确保仅显示对应按钮的内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 18:58:34