如何在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>
你原代码的关键问题
- 映射时固定使用了
busIcon,而非每个菜单对应的menu.icon,导致所有项显示同一个图标; - 数组内
icon值类型不统一(既有导入的模块,又有字符串路径),需要统一为上述两种方式之一。
内容的提问来源于stack exchange,提问作者Feth
相关产品推荐
相关产品推荐

