React应用中如何根据字符串值动态加载使用图标
问题原因
eval 方案报错核心原因有两个:
- 前端项目普遍使用ES模块搭配Webpack/Vite/Rollup这类打包工具做静态构建,
import导入的变量是模块作用域内的绑定,不会挂载到全局对象,eval默认从全局作用域查找变量,自然找不到局部导入的Icon1/Icon2。 - 生产环境打包时会对变量名做压缩混淆,就算作用域匹配正确,硬编码的字符串
'Icon1'也无法对应到混淆后的变量名,必然匹配失败,且eval本身存在XSS安全隐患,完全不推荐在业务代码里使用。
可行方案
方案1:手动维护图标映射表(优先推荐)
提前建立字符串标识和图标模块的映射关系,不管你拿到的动态值是变量名还是文件名都能适配,打包工具可以静态分析所有依赖,不会出现资源漏打包的问题,维护成本极低。
import * as Icon1 from 'images/img1.svg' import * as Icon2 from 'images/img2.svg' // 映射表key可根据业务传入的动态值灵活调整 const iconMap = { // 若传入的是变量名字符串,用以下key Icon1, Icon2, // 若传入的是文件名字符串,替换成以下key即可 // 'img1.svg': Icon1, // 'img2.svg': Icon2, } const Foo = () => { const theIcon = 'Icon1' // 动态获取的字符串值 // 配置兜底图标,避免key不存在导致组件渲染报错 const renderIcon = iconMap[theIcon] || Icon1 return (<> <AComponent icon={renderIcon}/> </>) }
后续新增图标只需要补充import语句和对应映射项即可。
方案2:批量导入图标(适合图标存量大的场景)
如果项目里有几十上百个图标,手动写import太繁琐,可以利用打包工具提供的批量导入能力自动生成映射表。
以Vite环境为例:
// 配置eager: true实现同步导入,无需异步加载 const iconFiles = import.meta.glob('images/*.svg', { eager: true, import: '*' }) // 自动生成「文件名: 图标模块」格式的映射表 const iconMap = Object.fromEntries( Object.entries(iconFiles).map(([fullPath, module]) => { const fileName = fullPath.split('/').pop() return [fileName, module] }) ) const Foo = () => { const theIcon = 'img1.svg' // 直接传文件名即可匹配 const renderIcon = iconMap[theIcon] return (<> <AComponent icon={renderIcon}/> </>) }
Webpack环境可以用require.contextAPI实现同样的批量导入效果。
注意:不要写完全动态的导入语句比如
import(images/${iconName}),这类写法会把匹配路径下的所有svg文件都打进生产包,会额外增加包体积,且路径规则不明确时很容易出现资源404的问题,图标数量少的时候优先选方案1。
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

