如何将JSON菜单数据按subcategory分组后嵌套map渲染对应菜品卡片
实现方案
第一步:先对原始菜单数据做分组处理
你拿到的是扁平结构的JSON数组,首先要按subcategory字段把同分类的菜品归到一组,用JS的reduce方法就能快速实现:
const rawMenu = [/* 此处替换为你的原始JSON菜单数据 */] // 分组后的结构为 {Snacks: [菜品1, 菜品2...], Starters: [菜品1...]} const groupedMenu = rawMenu.reduce((result, currentDish) => { const sub = currentDish.subcategory if (!result[sub]) result[sub] = [] result[sub].push(currentDish) return result }, {})
第二步:按分组渲染页面
根据你用的技术栈选对应方式即可:
方式1:Vue/React等前端框架实现(以Vue为例)
外层先遍历分组的子分类名渲染标题,内层遍历每个子分类下的菜品数组渲染卡片即可,示例代码:
<template> <div class="menu-wrapper"> <!-- 遍历所有子分类 --> <div v-for="(dishList, subName) in groupedMenu" :key="subName" class="subcategory-section"> <h2 class="sub-title">{{ subName }}</h2> <div class="dish-cards"> <!-- 遍历当前分类下的所有菜品 --> <div v-for="dish in dishList" :key="dish['eng-name']" class="dish-card"> <img :src="dish.image" :alt="dish['eng-name']" class="dish-pic"> <div class="dish-content"> <h3>{{ dish['eng-name'] }} <span class="thai-name">{{ dish['thai-name'] }}</span></h3> <p class="desc">{{ dish.description }}</p> <p class="price">单份/杯售价:{{ dish.price }} {{ dish.price2 ? `| 整瓶售价:${dish.price2}` : '' }}</p> <div class="tags"> <span v-for="tag in JSON.parse(dish.tags)" :key="tag" class="tag-item">{{ tag }}</span> </div> </div> </div> </div> </div> </div> </template>
方式2:原生JS实现
直接操作DOM生成页面结构即可,示例代码:
const menuContainer = document.querySelector('.menu-wrapper') // 遍历所有分组 Object.entries(groupedMenu).forEach(([subName, dishList]) => { // 插入子分类标题 const subTitle = document.createElement('h2') subTitle.className = 'sub-title' subTitle.innerText = subName menuContainer.appendChild(subTitle) const cardsWrap = document.createElement('div') cardsWrap.className = 'dish-cards' // 生成当前分类下所有菜品卡片 dishList.forEach(dish => { const tags = JSON.parse(dish.tags).map(tag => `<span class="tag-item">${tag}</span>`).join('') const card = document.createElement('div') card.className = 'dish-card' card.innerHTML = ` <img src="${dish.image}" alt="${dish['eng-name']}" class="dish-pic"> <div class="dish-content"> <h3>${dish['eng-name']} <span class="thai-name">${dish['thai-name']}</span></h3> <p class="desc">${dish.description}</p> <p class="price">单份/杯售价:${dish.price} ${dish.price2 ? `| 整瓶售价:${dish.price2}` : ''}</p> <div class="tags">${tags}</div> </div> ` cardsWrap.appendChild(card) }) menuContainer.appendChild(cardsWrap) })
可选优化点
- 数据量较大的话可以给菜品图片加懒加载,减少首屏加载压力
- 处理
tags字段转数组的时候加异常捕获,避免个别数据格式错误导致页面渲染失败 - 可以给子分类加锚点导航,方便用户快速跳转到对应分类
内容的提问来源于stack exchange,提问作者NewPathDev
相关产品推荐
相关产品推荐

