一 svg-sprite 图标的使用
1 进行 webpack 的配置
webpack.config.js:
module: {
rules: [
{
test: /.svg$/,
use: [{
loader: 'svg-sprite-loader',
options: {
symbolId: 'xxx-yyy-[name]-zzz'
}
}]
}
]
}
注意这里的 symbolId,最好配置一个比较全局唯一的名称。因为这里的 id,后面会作为 这个 html 标签的 id,存在于全局 DOM 当中。
2 在项目中引入 svg 资源
--1 首先在项目 src 目录下创建一个 svgs 目录,这里统一存放项目的 svg 图标资源。
--2 然后去下载图标资源。需要在阿里 iconfont 图标库当中,选择一个具体的图标 -> 点击下载按钮 -> 选择好 svg 图标的尺寸 -> 选择复制 SVG 代码
--3 在 svgs 目录当中创建一个 svg 文件,根据自己的需要命名,然后将刚刚复制的 svg 代码,粘贴在这个 svg 文件当中。
注意之后需要将该 svg 文件当中的 fill="xxx" 改为 fill="currentColor" 。
这是为了后面能使用 svg 标签的 css-color 属性去设置该图标的颜色。
--4 然后在 svgs 目录中创建一个 index.js 文件,作为使用图标的统一入口。
该文件当中通过 import './xxx.svg' 的形式,将一个个 svg 图标资源文件引入到项目代码当中。
--5 最后在项目的入口文件 main.js 当中,通过 imoport './svgs' 引入所有的 svg 图标资源。
3 在项目中使用 svg 图标
代码:
<template>
<svg class="svg-icon" style="font-size: 50px; color: red;">
<use xlink:href="#xxx-yyy-dede-zzz"></use>
</svg>
</template>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
将 svg-icon 作为 svg 图标的基础类,然后可以通过 font-size 这个 css 属性设置该图标的大小,通过 color 这个 css 属性设置该图标的颜色。
二 svg-sprite 图标技术的原理
1 svg-sprite-loader 的作用
--1 webpack 配置
module: {
rules: [
{
test: /.svg$/,
use: [{
loader: 'svg-sprite-loader',
options: {
symbolId: 'xxx-yyy-[name]-zzz'
}
}]
}
]
}
注意这里的 symbolId,最好配置一个比较全局唯一的名称。因为这里的 id,后面会作为 这个 html 标签的 id,存在于全局 DOM 当中。
--2 haha.svg 资源文件:
<svg
t="1680534954770"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="1211"
width="32"
height="32"
>
<path fill="currentColor"></path>
</svg>
--3 引入 svg 资源代码
import './haha.svg'
注意之后需要将该 svg 文件当中的 fill="xxx" 改为 fill="currentColor" 。
这是为了后面能使用 svg 标签的 css-color 属性去设置该图标的颜色。
--4 webpack 打包结果
dist/index.html:
<body>
<div id="box"></div>
<script src="/dist/js/main.6c8a5c9ea9.js"></script>
</body>
dist/js/main.6c8a5c9ea9.js:
var __webpack_modules__ = {
"./node_modules/svg-baker-runtime/browser-symbol.js": function() {},
"./node_modules/svg-sprite-loader/runtime/browser-sprite.build.js": function() {},
"./src/svgs/haha.svg": function() {},
}
--5 运行打包后代码
之后在我们运行该打包后的代码时,svg-sprite-loader 中的这些 svg 辅助函数,会在全局 DOM 的 body 下面创建 svg-symbol 标签。注意:创建 svg 标签的行为,一定是在我们运行代码后,是 js 运行时去动态创建的。
代码运行后,DOM 结构变为这样:
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
style="position: absolute; width: 0; height: 0"
aria-hidden="true"
id="__SVG_SPRITE_NODE__"
>
<symbol
xmlns="http://www.w3.org/2000/svg"
class="icon"
viewBox="0 0 1024 1024"
id="xxx-yyy-haha-zzz"
></symbol>
</svg>
等于说就是把我们在源 svg 文件内容,变成了这里的一个个 symbol 标签。源 svg 文件内容当中 svg 标签上面的 class、viewBox 属性,现在都跑到 symbol 标签上面来了。最重要的是,会给每一个 symbol 标签,都加上一个 id 属性,且这个 id 属性的值,就是我们在 webpack 中给 svg-sprite-loader 配置的 symbolId 值。
之后我们就可以通过这个 symbol 标签的 id 值,来引用需要的图标了。
其实这里相当于是生成了 svg 图标资源的定义,或者说是生成了 svg 图标的资源池,之后在项目中所有地方,都可以通过 id 来引入需要的 svg 图标。
2 svg-sprite-loader 处理完图标资源后,图标的使用原理
--1 使用图标代码
<template>
<svg class="svg-icon" style="font-size: 50px; color: red;">
<use xlink:href="#xxx-yyy-dede-zzz"></use>
</svg>
</template>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
--2 代码解析
使用 <svg><use xlink:href="#svg-icon-id"></use></svg> 代码来引用 svg 图标,这里的 svg 标签,才是真正的 svg 图标,是我们常规理解的 svg 图标标签。之前 svg-sprite-loader 生成的 svg-symbol 标签,只是 svg 图标的定义。
然后我们需要给项目中的所有使用 svg 图标地方的 svg 标签,加上一个基础 css 类,这里就是 svg-icon
这个基础类当中设置 width: 1em; height: 1em;,就是为了后面能够使用 font-size css 属性,来设置该 svg 标签的大小。
基础类中设置 fill: currentColor;,就是为了后面能够使用 color css 属性,来设置该 svg 标签的颜色。
三 svg-sprite 图标技术使用的优化
1 引入 svg 图标资源的优化
svgs/index.js:
// 将 ./svgs 目录下的所有 svg 文件进行打包
const context = require.context('./', false, /.svg$/)
// 获取 context key
const contextKeys = context.keys()
// 遍历 contextKeys
contextKeys.forEach(contetKey => {
// 使用这个 key 调用对应模块, 这里不需要获取导出结果, 只需要调用就行了
context(contetKey)
})
2 使用 svg 图标的优化
vue 组件 svg-icon.vue:
<template>
<svg class="svg-icon" aria-hidden="true">
<use :xlink:href="iconId"/>
</svg>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
iconName: {
type: String,
required: true
}
},
computed: {
iconId() {
return `#xxx-yyy-${this.iconName}-zzz`
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
使用该组件
<svg-icon icon-name="haha" :class="'my-icon'"></svg-icon>
<svg-icon icon-name="xixi" class="my-icon"></svg-icon>
3 使用 svgo-loader 压缩 svg 文件内容
webpack.config.js:
{
test: /.svg$/,
use: [
{
loader: 'svg-sprite-loader',
options: {
symbolId: 'xxx-yyy-[name]-zzz'
}
},
'svgo-loader'
]
}
4 使用自定义 loader 处理 svg 文件当中的 fill="#xxxxxx"
--1 在项目根目录创建 webpack-loaders 目录
--2 创建 svg-color-transform-loader / index.js 文件
module.exports = function(content, map, meta) {
return content.replace(/fill="#(\w{3}|\w{6})"/g, 'fill="currentColor"')
}
--3 修改 webpack 配置
webpack.config.js:
{
test: /.svg$/,
use: [
{
loader: 'svg-sprite-loader',
options: {
symbolId: 'xxx-yyy-[name]-zzz'
}
},
'./webpack-loaders/svg-color-transform-loader',
'svgo-loader'
]
}