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

ReactJS中动态加载SVG时src模板字符串失效问题及替代方案

React动态加载本地SVG图片的问题与解决方法

问题根源

Webpack(React项目默认打包工具)在编译阶段会静态解析require()的参数,它无法识别模板字符串里的动态变量。你的代码里require('../../assets/svg/${bullet.logoSrc}')会被Webpack当作完整的路径去查找,而非替换${bullet.logoSrc}变量后的真实路径,所以会出现“模块找不到”的错误。

解决方案

方案1:提前手动导入所有SVG资源

把需要用到的SVG逐个导入,直接在数组里引用导入后的资源:

// 提前导入所有SVG资源
import EducationIcon from '../../assets/svg/education.svg';
import WorkHistoryIcon from '../../assets/svg/work-history.svg';
import ProgrammingSkillsIcon from '../../assets/svg/programming-skills.svg';
import ProjectsIcon from '../../assets/svg/projects.svg';
import InterestsIcon from '../../assets/svg/interests.svg';

const resumeBullets = [
    { label: "education", logoSrc: EducationIcon },
    { label: "Work History", logoSrc: WorkHistoryIcon },
    { label: "Skills", logoSrc: ProgrammingSkillsIcon },
    { label: "Projects", logoSrc: ProjectsIcon },
    { label: "Interests", logoSrc: InterestsIcon },
];

const getBullets = () => {
    return resumeBullets.map((bullet, index) => (
        <div
            onClick={() => handleCarousal(index)}
            className={index === selectedBulletIndex ? "bullet selected-bullet" : "bullet"}
            key={index}
        >
            <img 
                className='bullet-logo'
                src={bullet.logoSrc}
                alt='resume section icon'
            />
        </div>
    ))
};

这种方式最稳定,Webpack能精准识别并打包所有资源,不会出现路径解析问题。

方案2:用require.context批量导入SVG

如果SVG数量较多,手动导入太繁琐,可以用Webpack提供的require.context批量加载指定目录下的SVG:

// 创建SVG资源上下文:指定目录、是否递归子目录、匹配.svg后缀的文件
const svgContext = require.context('../../assets/svg', false, /\.svg$/);

const resumeBullets = [
    { label: "education", logoSrc: "education.svg" },
    { label: "Work History", logoSrc: "work-history.svg" },
    { label: "Skills", logoSrc: "programming-skills.svg" },
    { label: "Projects", logoSrc: "projects.svg" },
    { label: "Interests", logoSrc: "interests.svg" },
];

const getBullets = () => {
    return resumeBullets.map((bullet, index) => (
        <div
            onClick={() => handleCarousal(index)}
            className={index === selectedBulletIndex ? "bullet selected-bullet" : "bullet"}
            key={index}
        >
            <img 
                className='bullet-logo'
                // 通过上下文对象获取对应SVG资源
                src={svgContext(`./${bullet.logoSrc}`)}
                alt='resume section icon'
            />
        </div>
    ))
};

require.context会在编译时扫描目标目录的所有匹配文件,生成一个上下文对象,通过传入相对路径就能获取对应的资源模块,适合批量处理大量SVG。

方案3:将SVG作为React组件导入(推荐)

如果你的项目用的是Create React App(默认集成了@svgr/webpack),可以直接把SVG当作React组件导入使用,这种方式更灵活,还能直接通过props控制样式:

// 导入SVG为React组件
import EducationIcon from '../../assets/svg/education.svg';
import WorkHistoryIcon from '../../assets/svg/work-history.svg';
import ProgrammingSkillsIcon from '../../assets/svg/programming-skills.svg';
import ProjectsIcon from '../../assets/svg/projects.svg';
import InterestsIcon from '../../assets/svg/interests.svg';

const resumeBullets = [
    { label: "education", Icon: EducationIcon },
    { label: "Work History", Icon: WorkHistoryIcon },
    { label: "Skills", Icon: ProgrammingSkillsIcon },
    { label: "Projects", Icon: ProjectsIcon },
    { label: "Interests", Icon: InterestsIcon },
];

const getBullets = () => {
    return resumeBullets.map((bullet, index) => {
        const { Icon } = bullet;
        return (
            <div
                onClick={() => handleCarousal(index)}
                className={index === selectedBulletIndex ? "bullet selected-bullet" : "bullet"}
                key={index}
            >
                {/* 直接使用SVG组件,通过className控制样式 */}
                <Icon className='bullet-logo' />
            </div>
        )
    })
};

这种方式的优势在于,SVG是React组件,可以直接通过className修改样式,若SVG内部使用了currentColor属性,还能通过style={{ color: 'xxx' }}直接修改图标颜色,扩展性更强。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:45:00