You need to enable JavaScript to run this app. React中字符串形式SVG图标无法正常渲染的解决方法
优惠活动
大模型
产品
解决方案
定价
更多

React中字符串形式SVG图标无法正常渲染的解决方法

React中SVG字符串渲染失败的原因与正确实现方案

现有尝试的失败根因

  • 直接用<img src={filled_lock} />无法生效:img标签的src属性仅支持有效资源地址(如网络路径、本地路径、Blob地址、Base64编码内容),无法直接解析原生SVG字符串为图片资源,浏览器会将字符串内容判定为无效路径发起请求,自然无法加载图标。
  • 错误使用dangerouslySetInnerHTML的场景有两个核心问题:
    • 语法传值错误:正确的属性值应当是待注入的HTML字符串本身,实际代码中多包了一层对象,导致注入的内容不是合法的SVG文本。
    • 内容转义未还原:存储的filled_lock字符串包含大量HTML实体(如&lt;、&quot;),未还原为原生HTML标签字符的话,注入DOM后只会显示为纯文本,不会渲染为SVG节点。

可行的正确实现方案

方案1:修正dangerouslySetInnerHTML注入逻辑

  1. 先对存储的SVG字符串做实体还原、首尾空格清理:
    // 还原实体、清理多余空格
    const sanitizedLockSvg = filled_lock
      .replace(/&lt;/g, '<')
      .replace(/&gt;/g, '>')
      .replace(/&quot;/g, '"')
      .trim();
    
  2. 按照React的规则正确传入注入内容,不要额外嵌套对象:
    <div dangerouslySetInnerHTML={{ __html: sanitizedLockSvg }} />
    
    注意:该方式仅适用于来源可信的SVG内容,避免引入XSS安全风险。

方案2:生成临时Blob地址配合img标签渲染

适合不想直接向DOM注入原生HTML的场景:

  1. 用清洗完成的合法SVG字符串生成Blob对象,转成临时的ObjectURL
  2. 将临时地址赋值给img标签的src属性
    // 组件挂载时生成Blob地址
    const lockImgUrl = useMemo(() => {
      const svgBlob = new Blob([sanitizedLockSvg], { type: 'image/svg+xml' });
      return URL.createObjectURL(svgBlob);
    }, [sanitizedLockSvg]);
    
    // 组件卸载时释放内存,避免泄漏
    useEffect(() => {
      return () => URL.revokeObjectURL(lockImgUrl);
    }, [lockImgUrl]);
    
    return <img src={lockImgUrl} width="30" height="30" alt="锁定状态图标" />;
    

方案3:将SVG抽为独立React组件(推荐)

长期维护最稳妥的实现方式,不需要额外处理字符串转义、内存释放等问题,直接将SVG结构迁移为JSX节点即可,React会自动处理属性转义:

const FilledLockIcon = ({ size = 30, color = '#668cb3' }) => {
  return (
    <svg 
      width={size} 
      height={size} 
      viewBox="0 0 15 15" 
      version="1.1" 
      xmlns="http://www.w3.org/2000/svg"
    >
      <g id="Symbols" stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
        <g id="Icon/Locked/Filled/Light">
          <rect id="Rectangle" fill="#D8D8D8" opacity="0" x="-1" y="-1" width="15" height="15" />
          <g id="Icon/Locked/Filled/Dark" transform="translate(-1.000000, -1.000000)">
            <rect id="Rectangle" fill="#D8D8D8" opacity="0" x="0" y="0" width="15" height="15" />
            <g transform="translate(3.000000, 1.000000)" fill={color}>
              <path d="M7.75,5.5 L2.25,5.5 L2.25,3.25 C2.25,1.73365625 3.483875,0.5 5.0005,0.5 C6.51659375,0.5 7.75,1.73365625 7.75,3.25 L7.75,5.5 Z M5.25,9.4685 L5.25,10.5 L4.75,10.5 L4.75,9.4685 C4.3186875,9.35746875 4,8.9659375 4,8.5 C4,7.94771875 4.44771875,7.5 5,7.5 C5.55228125,7.5 6,7.94771875 6,8.5 C6,8.9659375 5.6813125,9.35746875 5.25,9.4685 Z M8.25,5.5 L8.25,3.25 C8.25,1.4553125 6.7949375,0 5.0005,0 C3.2050625,0 1.75,1.4553125 1.75,3.25 L1.75,5.5 L0,5.5 L0,13 L10,13 L10,5.5 L8.25,5.5 Z" />
              <path d="M5,8 C4.7243125,8 4.5,8.2243125 4.5,8.5 C4.5,8.7756875 4.7243125,9 5,9 C5.2756875,9 5.5,8.7756875 5.5,8.5 C5.5,8.2243125 5.2756875,8 5,8" />
            </g>
          </g>
        </g>
      </g>
    </svg>
  )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.01 11:06:04