如何遍历SVG对象数组在HTML中渲染且不被Chrome拦截
问题原因
直接将裸SVG字符串传入<img>标签的src属性时,浏览器会将其识别为无效资源路径,触发安全拦截。src属性仅接受合法的资源路径、或符合格式规范的Data URL,无法直接解析未经过处理的裸SVG标记。
可行解决方案
以下两种方案都支持批量遍历渲染全量图标,不需要将SVG拆分为上百个单独文件,完全复用你现有的数组存储结构。
方案1:转换为Data URL传入src(改动最小)
只需要给SVG字符串拼接合法的Data URL前缀,同时做特殊字符编码即可,原有渲染逻辑几乎不需要调整:
<div className="link-list"> { userInterfaceIcons.map((icon, i) => { // 拼接SVG类型的Data URL头,编码特殊字符避免解析异常 const iconSrc = `data:image/svg+xml;utf8,${encodeURIComponent(icon.data)}` return( <a className="link-item" key={i} > <img src={iconSrc} alt={icon.name} /> <span> <strong>{icon.name}</strong> Easy setup for TypeScript, SCSS and more. </span> </a> ) }) } </div>
注意:必须通过encodeURIComponent处理SVG字符串内的引号、尖括号、换行等特殊字符,否则会出现格式解析错误。该方案渲染效果和加载本地独立SVG文件完全一致,不会触发浏览器拦截。
方案2:直接内联渲染SVG(灵活度最高,推荐)
如果后续需要通过CSS控制SVG的尺寸、填充色、描边等样式(比如做主题适配、hover交互),直接将SVG内联渲染到DOM中比使用img标签更方便。由于你的图标数据是本地维护的静态内容,不存在第三方注入风险,可以直接通过dangerouslySetInnerHTML注入:
<div className="link-list"> { userInterfaceIcons.map((icon, i) => { return( <a className="link-item" key={i} > <span className="icon-wrap" dangerouslySetInnerHTML={{__html: icon.data}} /> <span> <strong>{icon.name}</strong> Easy setup for TypeScript, SCSS and more. </span> </a> ) }) } </div>
该方案不会产生额外的资源请求,渲染性能更好。渲染后生成的是原生SVG节点,你可以直接通过CSS自定义样式,比如通过.icon-wrap svg { width: 24px; height: 24px; fill: currentColor; }让图标继承文字颜色,适配深色/浅色主题非常方便。
避坑提示
- 禁止直接将未编码的裸SVG字符串传入img的src属性,浏览器无法识别该格式必然触发拦截
- 如果使用TypeScript,只要
icon.data的类型定义为string,上述两种方案都不需要额外补充类型声明 - 内联渲染方案仅适用于可信的静态SVG内容,禁止用来渲染用户上传的不可信SVG内容,避免XSS风险
内容的提问来源于stack exchange,提问作者Khepf
相关产品推荐
相关产品推荐

