文章目录
- [一、SVG 图标管理的优势](#一、SVG 图标管理的优势)
- [二、SVG 图标存储结构](#二、SVG 图标存储结构)
- [三、SVG 图标的加载与注册机制](#三、SVG 图标的加载与注册机制)
-
- [1. 自动加载核心代码](#1. 自动加载核心代码)
- [2. 工作原理](#2. 工作原理)
- [四、svg-sprite-loader 配置](#四、svg-sprite-loader 配置)
-
- [1. 安装依赖](#1. 安装依赖)
- [2. Vue CLI 配置](#2. Vue CLI 配置)
- [3. 传统 Webpack 配置](#3. 传统 Webpack 配置)
- [五、SVG 图标组件实现](#五、SVG 图标组件实现)
- [六、SVG 图标的完整处理流程](#六、SVG 图标的完整处理流程)
-
- [1. 构建阶段](#1. 构建阶段)
- [2. 运行阶段](#2. 运行阶段)
- [七、SVG 优化配置](#七、SVG 优化配置)
-
- [1. SVGO 配置文件](#1. SVGO 配置文件)
- [2. 优化脚本](#2. 优化脚本)
- [3. 执行优化](#3. 执行优化)
- [八、在项目中使用 SVG 图标](#八、在项目中使用 SVG 图标)
-
- [1. 基本使用](#1. 基本使用)
- [2. 颜色控制](#2. 颜色控制)
- [3. 大小控制](#3. 大小控制)
一、SVG 图标管理的优势
- 矢量图形:无限缩放不失真
- 文件体积小:通常比位图小,加载快
- 可编辑性强:可通过 CSS 和 JavaScript 修改
- 支持动画:可实现丰富的交互动画效果
- 响应式:自适应不同屏幕尺寸
- 颜色可控:支持通过 CSS 统一控制颜色
二、SVG 图标存储结构
src/
├── icons/
│ ├── index.js # 图标注册文件
│ ├── svgo.yml # SVGO 优化配置
│ └── svg/ # SVG 文件存储目录
│ ├── user.svg
│ ├── password.svg
│ └── ...
- 存储位置 :
src/icons/svg目录 - 文件格式 :标准
.svg文件 - 组织方式 :扁平化管理,直接放入
svg目录
三、SVG 图标的加载与注册机制
1. 自动加载核心代码
文件 :src/icons/index.js
javascript
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg component
// 全局注册组件
Vue.component('svg-icon', SvgIcon)
// 自动加载所有 SVG 文件
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)
2. 工作原理
-
创建文件上下文:
require.context('./svg', false, /\.svg$/)创建一个文件加载上下文- 扫描
src/icons/svg目录下的所有.svg文件
-
批量加载:
req.keys()返回所有匹配文件的相对路径数组map(requireContext)对每个路径执行加载操作
-
全局注册:
Vue.component('svg-icon', SvgIcon)全局注册组件- 全项目可直接使用
<svg-icon>标签
四、svg-sprite-loader 配置
1. 安装依赖
bash
# 安装 svg-sprite-loader
npm install svg-sprite-loader --save-dev
# 安装 SVGO(可选,用于优化 SVG)
npm install svgo --save-dev
2. Vue CLI 配置
文件 :vue.config.js
javascript
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
chainWebpack(config) {
// 排除默认 SVG 处理
config.module
.rule('svg')
.exclude.add(resolve('src/icons'))
.end()
// 配置 svg-sprite-loader
config.module
.rule('icons')
.test(/\.svg$/)
.include.add(resolve('src/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
.end()
}
}
3. 传统 Webpack 配置
javascript
const path = require('path')
module.exports = {
module: {
rules: [
{
test: /\.svg$/,
include: path.resolve(__dirname, 'src/icons'),
use: [
{
loader: 'svg-sprite-loader',
options: {
symbolId: 'icon-[name]'
}
}
]
}
]
}
}
五、SVG 图标组件实现
文件 :src/components/SvgIcon/index.vue
html
<template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
import { isExternal } from '@/utils/validate'
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
isExternal() {
return isExternal(this.iconClass)
},
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
},
styleExternalIcon() {
return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
}
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover!important;
display: inline-block;
}
</style>
六、SVG 图标的完整处理流程
1. 构建阶段
- 文件准备 :将 SVG 文件放入
src/icons/svg目录 - 依赖安装 :
npm install安装所有依赖 - SVG 优化 :
npm run svgo优化 SVG 文件 - 项目构建 :
npm run build或npm run dev - Webpack 处理 :
- svg-sprite-loader 将 SVG 文件转换为
<symbol>元素 - 生成唯一的
symbolId(如icon-user) - 合并所有
<symbol>元素到一个<svg>元素 - 将生成的
<svg>元素注入到 HTML 页面
- svg-sprite-loader 将 SVG 文件转换为
2. 运行阶段
- 应用启动 :加载
src/main.js,引入./icons - 组件注册 :全局注册
svg-icon组件 - 图标使用 :在模板中使用
<svg-icon icon-class="图标名"> - 浏览器渲染 :
- 解析
<svg-icon>组件 - 生成对应的
<use>元素 - 通过
xlink:href查找并渲染对应的<symbol> - 应用 CSS 样式(如颜色继承)
- 解析
七、SVG 优化配置
1. SVGO 配置文件
文件 :src/icons/svgo.yml
yaml
plugins:
- removeAttrs:
attrs:
- 'fill' # 移除填充颜色属性
- 'fill-rule' # 移除填充规则属性
2. 优化脚本
文件 :package.json
json
"scripts": {
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
}
3. 执行优化
bash
npm run svgo
优化效果:
- 移除硬编码的
fill属性,使图标可继承父元素颜色 - 移除不必要的属性,减小 SVG 文件体积
- 确保所有图标风格一致
八、在项目中使用 SVG 图标
1. 基本使用
html
<template>
<div>
<!-- 基本使用 -->
<svg-icon icon-class="user" />
<!-- 带自定义类名 -->
<svg-icon icon-class="password" class="custom-class" />
<!-- 绑定事件 -->
<svg-icon icon-class="search" @click="handleSearch" />
</div>
</template>
2. 颜色控制
html
<template>
<div>
<!-- 默认颜色 -->
<svg-icon icon-class="user" />
<!-- 自定义颜色 -->
<svg-icon icon-class="user" style="color: red;" />
<!-- 主题色 -->
<svg-icon icon-class="user" class="theme-color" />
</div>
</template>
<style scoped>
.theme-color {
color: var(--primary-color);
}
</style>
3. 大小控制
html
<template>
<div>
<!-- 默认大小 -->
<svg-icon icon-class="user" />
<!-- 自定义大小 -->
<svg-icon icon-class="user" style="font-size: 24px;" />
<!-- 不同尺寸 -->
<svg-icon icon-class="user" class="icon-large" />
<svg-icon icon-class="user" class="icon-small" />
</div>
</template>
<style scoped>
.icon-large {
font-size: 32px;
}
.icon-small {
font-size: 16px;
}
</style>