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

如何将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 16:48:01