创建react项目
安装create-react-app:
npm install -g create-react-app
创建react项目:
npx create-react-app <项目名称>// 注意:名字不能包含大写字母。
进入项目文件夹(我的是demo):
cd demo
npm start
svg-sprite-loader
GitHub:svg-sprite-loader
原理:svg-sprite-loader 会把svg 塞到一个个 symbol 中,合成一个大的 svg。最后将这个大的 svg 放入 body 中。symbol的id如果不特别指定,就是你的文件名。
利用 svg 的 symbol 元素,将每个 icon 包裹在 symbol 中,通过 use 使用该 symbol。
----------摘自《在React中使用SVG和组件化》和《使用svg-sprite-loader优化Icon》
在页面上形成这样的元素:(摘自使用svg-sprite-loader优化Icon)
我们的每一个 icon 都对应着一个 symbol 元素,这个时候我们就可以在页面使用 svg use 啦。
<body>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="__SVG_SPRITE_NODE__">
<symbol xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 1024 1024" id="xxx">// id 是 icon 名
<!-- 这块是 path 标签 -->
</symbol>
<symbol xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 1024 1024" id="xxx">// id 是 icon 名
<!-- 这块是 path 标签-->
</symbol>
</svg>
</body>
安装
npm i svg-sprite-loader -D
配置 webpack.config.js
这一步必须要修改,由于我创建react项目的方式没有暴露webpack配置文件,所以我一开始没有修改。运行后发现页面是空白的,打开控制台发现是因为没有合理加载svg图标,这是因为webpack中本身就有对svg的处理规则,并且file-loader还有一个默认的地址。
访问webpack配置文件有两种方式:
- 弹出配置文件,但注意这个操作不可逆。一旦弹出,就无法回去。
npm run eject
成功后会出现一个 config 文件夹:
- 如果不想弹出,只想查看配置,可以在这个目录找到:
/node_modules/react-scripts/config
在配置文件中添加如下配置:
{
test: /\.svg$/,
use: [
{
loader: require.resolve('svg-sprite-loader'),
options: {
//SymbolId:'icon-[name]' // 这一行可有可无
}
}
]
},
这里 SymbolId 这一行可有可无,SymbolId对应的是使用时 use 标签的xlinkHref属性,也就是说如果采用了 SymbolId:‘icon-[name]’ 的配置,那么使用时的语句应该是 “icon-” 开头的;如果没有特别配置 SymbolId, 那么使用的时候用的是下面注释掉的那种方式:
踩坑: webpack中原来就有对svg文件的处理,我用include
和exclude
试了好多次都不成功,最后把原来的注释掉了,只保留上面的配置才生效的。。。
重启项目以后,可以在页面看到svg标签了。(因为我这里是整个写完以后才写的这篇文章记录整个过程,所以这里就放后面弄好的截图啦)
我期望的用法是这样的:
<Icon name="account" color="red" size={
[50,50]}/>
或者 size={
50} 这样的写法
所以需要三个参数:
- 名称(name)
- 颜色(color)
- 尺寸(size)。
到目前为止,通过名称引入svg图片的需求就可以基本满足了。
size的实现比较简单,就不做太多赘述了(后面的代码中也体现了处理size的过程),直接在svg上添加属性就可以了,举个简单的例子:
return (
<svg
width={
200} // 把这里换成变量就可以了,或者将样式统一放在一个对象里,然后用展开符也行
height={
200}
aria-hidden="true"
>
<use xlinkHref={
iconName} />
</svg>
)
Icon组件代码:
import React, {
useMemo, useState, useEffect } from 'react'
const Icon = ({
name,width,height}) => {
const [svgModule, setSvgModule] = useState();
const getSvg = async () => {
const svg = await import(`../../icons/svg/${
name}.svg`)
setSvgModule(svg)
}
const iconName = useMemo(() => {
if (svgModule && svgModule.default) {
return `#${
svgModule.default.id}`
}
}, [name, svgModule])
useEffect(() => {
getSvg()
}, [])
return (
<svg
width={
width}
height={
height}
aria-hidden="true"
>
<use xlinkHref={
iconName} />
</svg>
)
}
export default Icon
这里获取 svg 图片的方式是通过传入的 name 去引入的,可以打印看一下的内容(也就理解 svgModule.default.id
是什么意思了):
svgo-loader
GitHub:svgo-loader
SVG 文件,尤其是从各种编辑器导出的文件,通常包含大量冗余和无用的信息。这可以包括编辑器元数据、注释、隐藏元素、默认值或非最佳值以及其他可以安全删除或转换而不影响 SVG 渲染结果的内容。
-------摘自在React中使用SVG和组件化
SVGO 将 SVG-as-XML 数据转换为 SVG-as-JS AST 表示形式。然后在所有AST数据项上运行并执行一些操作,最后,SVGO 再将 AST 转换回 SVG-as-XML 数据字符串。
SVGO 是 svg 优化器,包含很多插件。它可以删除和修改SVG元素,折叠内容,移动属性等等。
--------摘自《使用svg-sprite-loader优化Icon》
安装svgo-loader:
npm install svgo-loader
配置 webpack.config.js:
{
test: /\.svg$/,
use: [
{
loader: 'svg-sprite-loader', options: {
} },
+ {
loader: 'svgo-loader', options: {
plugins:[ // 可不加
{
removeAttrs:{
attrs:'fill'}}//删除svg原本的fill属性,方便修改图标颜色
]
}
}
]
}
引入项目中的 svg 文件会经过 svgo-loader => svg-sprite-loader 的处理。先处理 svg 图像,然后在页面中生成 svg-symbols。-------摘自在React中使用SVG和组件化
颜色的处理比较麻烦,写在下一篇文章了。
下一篇:关于svg颜色部分的处理