如何在React项目中正确使用SVG Sprite?
在React中使用SVG Sprite的问题
我在Stack Overflow上搜索了许多相关问题,但都没有解决我的问题。我拥有一个SVG Sprite:
<svg width="25" height="25" > <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" id="dota-icon"> <path d="M46,8V6c0-0.552-0.447-1-1-1h-4c-0.396,0-0.714,0.026-1,0.1V5c0-0.552-0.447-1-1-1h-6c-1.734,0-2.361,0.984-2.729,2h-0.812 C29.226,5.689,29,5.286,29,5c0-0.552-0.447-1-1-1h-7c-0.511,0-0.94,0.393-0.995,0.9C19.982,5.11,19.557,6,18.896,6h-2.74 c-0.065-0.077-0.159-0.22-0.24-0.403C15.756,5.234,15.396,5,15,5H5C4.447,5,4,5.448,4,6v8c0,2.823,0.825,6.397,0.999,7.118 l-0.008,1.515l-0.678,0.641C4.113,23.462,4,23.725,4,24v4c0,0.266,0.105,0.52,0.293,0.707L5,29.414v4.424l-0.948,2.846 c-0.061,0.181-0.068,0.374-0.021,0.559l0.929,3.718l-0.907,2.724c-0.103,0.305-0.051,0.641,0.137,0.901C4.377,44.846,4.679,45,5,45 h14c0.266,0,0.52-0.105,0.707-0.293l0.09-0.09C20.328,45.343,21.067,46,22,46h3c0.736,0,1.38-0.321,1.947-0.605 C27.335,45.2,27.736,45,28,45h5c0.266,0,0.52-0.105,0.707-0.293l0.243-0.243c0.063,0.08,0.123,0.159,0.182,0.235 C34.623,45.339,35.13,46,36,46h5c0.553,0,1-0.447,1-1v-0.719l2.758,0.688c0.299,0.077,0.616,0.007,0.86-0.184 c0.243-0.19,0.384-0.483,0.382-0.793c-0.001-0.098-0.063-9.91,0-14.98c0.003-0.27-0.103-0.529-0.293-0.72L45,27.586V23 c0-0.265-0.105-0.52-0.293-0.707l-0.49-0.49l0.605-1.21l0.885-0.885C45.895,19.52,46,19.265,46,19l-0.015-5.01 c0-0.081-0.01-0.161-0.029-0.24l-0.896-3.632l0.835-1.67C45.964,8.309,46,8.155,46,8z M34.089,12l3.044,2l-1.015,6L28,14L34.089,12z M15,38l-4-3l2-7l8,8L15,38z M36.2,37h-4.667L11,12.926L14.733,12L39,30.518L36.2,37z"></path> </symbol> </svg>
我尝试通过以下方式使用它:
<use xlinkHref="../../img/svg-sprite.svg#icon-dota" />
或者:
<svg width="10" height="10"> <use xlinkHref="../../img/svg-sprite.svg#icon-dota"></use> </svg>
之后我尝试将其作为ReactComponent导入,但遇到了错误:Cannot find module "../../img/svg-sprite.svg" or associated type declarations.
我找到了一个解决方案但没起作用:
const webpack = require('webpack'); module.exports = { module: { rules: [ //... { test: /\.svg$/, use: ['@svgr/webpack'], }, ], }, //... };
解决方法
1. 修正ID匹配错误
首先注意:你的Sprite中symbol的id是dota-icon,但你使用时写的是#icon-dota,ID不匹配是核心问题之一,先统一改为#dota-icon。
2. 直接在HTML中引入Sprite(最简单方案)
- 将
svg-sprite.svg放在项目的public目录下 - 在
public/index.html的<body>开头添加:
<svg style="display: none;"> <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" id="dota-icon"> <path d="M46,8V6c0-0.552-0.447-1-1-1h-4c-0.396,0-0.714,0.026-1,0.1V5c0-0.552-0.447-1-1-1h-6c-1.734,0-2.361,0.984-2.729,2h-0.812 C29.226,5.689,29,5.286,29,5c0-0.552-0.447-1-1-1h-7c-0.511,0-0.94,0.393-0.995,0.9C19.982,5.11,19.557,6,18.896,6h-2.74 c-0.065-0.077-0.159-0.22-0.24-0.403C15.756,5.234,15.396,5,15,5H5C4.447,5,4,5.448,4,6v8c0,2.823,0.825,6.397,0.999,7.118 l-0.008,1.515l-0.678,0.641C4.113,23.462,4,23.725,4,24v4c0,0.266,0.105,0.52,0.293,0.707L5,29.414v4.424l-0.948,2.846 c-0.061,0.181-0.068,0.374-0.021,0.559l0.929,3.718l-0.907,2.724c-0.103,0.305-0.051,0.641,0.137,0.901C4.377,44.846,4.679,45,5,45 h14c0.266,0,0.52-0.105,0.707-0.293l0.09-0.09C20.328,45.343,21.067,46,22,46h3c0.736,0,1.38-0.321,1.947-0.605 C27.335,45.2,27.736,45,28,45h5c0.266,0,0.52-0.105,0.707-0.293l0.243-0.243c0.063,0.08,0.123,0.159,0.182,0.235 C34.623,45.339,35.13,46,36,46h5c0.553,0,1-0.447,1-1v-0.719l2.758,0.688c0.299,0.077,0.616,0.007,0.86-0.184 c0.243-0.19,0.384-0.483,0.382-0.793c-0.001-0.098-0.063-9.91,0-14.98c0.003-0.27-0.103-0.529-0.293-0.72L45,27.586V23 c0-0.265-0.105-0.52-0.293-0.707l-0.49-0.49l0.605-1.21l0.885-0.885C45.895,19.52,46,19.265,46,19l-0.015-5.01 c0-0.081-0.01-0.161-0.029-0.24l-0.896-3.632l0.835-1.67C45.964,8.309,46,8.155,46,8z M34.089,12l3.044,2l-1.015,6L28,14L34.089,12z M15,38l-4-3l2-7l8,8L15,38z M36.2,37h-4.667L11,12.926L14.733,12L39,30.518L36.2,37z"></path> </symbol> </svg>
- 在React组件中直接使用:
<svg width="25" height="25"> <use href="#dota-icon" /> </svg>
注意:xlinkHref是SVG 1.1的旧属性,现代浏览器支持直接用href。
3. 使用svg-sprite-loader打包Sprite
适合需要通过webpack管理资源的场景:
- 安装依赖:
npm install svg-sprite-loader --save-dev
- 修改webpack配置(Create React App项目需用
react-app-rewired或 eject):
module.exports = { module: { rules: [ { test: /\.svg$/, loader: 'svg-sprite-loader', options: { symbolId: 'icon-[name]' // 生成的symbol ID格式,可自定义 } } ] } };
- 在React组件中导入并使用:
import '../../img/svg-sprite.svg'; export default function DotaIcon() { return ( <svg width="25" height="25"> <use href="#dota-icon" /> </svg> ); }
4. 解决TypeScript类型声明问题
如果是TypeScript项目,创建src/types/svg.d.ts文件:
declare module '*.svg' { const content: string; export default content; }
然后在tsconfig.json中确保包含该类型文件:
{ "compilerOptions": { "typeRoots": ["./src/types", "./node_modules/@types"] } }
关键注意事项
- 不要用
@svgr/webpack处理Sprite文件,它的作用是将单个SVG转换为React组件,不适合多symbol的Sprite - 始终确保
use的href与Sprite中symbol的id完全匹配 - 检查文件路径是否正确,webpack解析路径时相对于当前组件文件位置
内容的提问来源于stack exchange,提问作者Богдан Гапоненко
相关产品推荐
相关产品推荐

