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

如何在Next.js 13应用中从public文件夹创建图标数组并映射?

解决Next.js 13.4中SVG图标数组映射渲染问题

你当前的核心问题是映射时没有使用菜单对应的图标变量,且数组内图标值类型不统一,这里提供两种实用方案来解决:


方案一:导入所有SVG图标(类似Material UI使用逻辑)

和你之前用Material UI图标的思路一致,先把需要的SVG逐个导入,再在数组中引用这些导入的变量:

步骤1:导入所有需要的图标

import Image from 'next/image'
// 逐个导入public目录下的SVG
import busIcon from '../public/busIcon.svg'
import routeIcon from '../public/route.svg'
import scheduleIcon from '../public/schedule.svg'
import bookingIcon from '../public/booking.svg'
import ticketingIcon from '../public/ticketing.svg'
import checkInIcon from '../public/check-in.svg'
import departureIcon from '../public/departure.svg'
import trackingIcon from '../public/tracking.svg'
import financeIcon from '../public/finance.svg'
import reportsIcon from '../public/reports.svg'
import manageUserIcon from '../public/manage user.svg'
import helpIcon from '../public/help.svg'

步骤2:统一定义菜单数组

每个菜单的icon字段使用导入的变量,无图标项设为null:

const Menus = [
  { title: "Bus", icon: busIcon },
  { title: "Route", icon: routeIcon },
  { title: "Schedule", icon: scheduleIcon },
  { title: "Booking", icon: bookingIcon },
  { title: "Ticketing", icon: ticketingIcon },
  { title: "Check-in", icon: checkInIcon },
  { title: "Departure", icon: departureIcon },
  { title: "Tracking", icon: trackingIcon },
  { title: "Finance", icon: financeIcon },
  { title: "Reports", icon: reportsIcon },
  { title: "Manage User", icon: manageUserIcon },
  { title: "Help", icon: helpIcon },
  { title: "Logout", icon: null },
]

步骤3:映射渲染菜单

渲染时使用menu.icon,并处理无图标的情况:

<ul className='pt-2'>
  {Menus.map((menu, index) => (
    <li key={index} className='text-dark-green text-sm flex items-center gap-x-4 cursor-pointer p-2 hover:bg-light-gray rounded-md'>
      {menu.icon && (
        <span className='text-2xl block'>
          <Image 
            src={menu.icon} 
            alt={`${menu.title} 图标`} 
            width={24} 
            height={24} // 可根据需求调整尺寸
          />
        </span>
      )}
      <span className='text-base font-medium flex-1'>{menu.title}</span>
    </li>
  ))}
</ul>

方案二:直接使用public路径(无需提前导入)

Next.js的Image组件支持直接引用public目录下的文件路径,无需提前导入,更适合图标较多的场景:

步骤1:定义菜单数组

icon字段直接写public目录下的文件名:

const Menus = [
  { title: "Bus", icon: "busIcon.svg" },
  { title: "Route", icon: "route.svg" },
  { title: "Schedule", icon: "schedule.svg" },
  { title: "Booking", icon: "booking.svg" },
  { title: "Ticketing", icon: "ticketing.svg" },
  { title: "Check-in", icon: "check-in.svg" },
  { title: "Departure", icon: "departure.svg" },
  { title: "Tracking", icon: "tracking.svg" },
  { title: "Finance", icon: "finance.svg" },
  { title: "Reports", icon: "reports.svg" },
  { title: "Manage User", icon: "manage user.svg" },
  { title: "Help", icon: "help.svg" },
  { title: "Logout", icon: "" },
]

步骤2:映射渲染菜单

渲染时给路径加上根目录前缀/,并处理空图标:

<ul className='pt-2'>
  {Menus.map((menu, index) => (
    <li key={index} className='text-dark-green text-sm flex items-center gap-x-4 cursor-pointer p-2 hover:bg-light-gray rounded-md'>
      {menu.icon && (
        <span className='text-2xl block'>
          <Image 
            src={`/${menu.icon}`} 
            alt={`${menu.title} 图标`} 
            width={24} 
            height={24}
          />
        </span>
      )}
      <span className='text-base font-medium flex-1'>{menu.title}</span>
    </li>
  ))}
</ul>

你原代码的关键问题

  1. 映射时固定使用了busIcon,而非每个菜单对应的menu.icon,导致所有项显示同一个图标;
  2. 数组内icon值类型不统一(既有导入的模块,又有字符串路径),需要统一为上述两种方式之一。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 13:13:09