原生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
相关产品推荐
相关产品推荐

