本教程教大家如何在 Vue 中引入 SVG icon 图标系统,然后教大家如何一步步搭建一套 SVG 图标系统,下图为跟随本教程最终的搭建效果。
本教程所涉及到的案例源码可在 github 下载:https://github.com/HiJiangChuan/using-svg-and-vue-complete-guide
目前 网站/app 内展示图标的主流方案就是 svg-icon
方法。我先带大家来回顾一下 icon
的演变史。然后详细讲解如何在 vue
中使用 svg-icon
方法。最后跟着我的教程一起搭一套 SVG 图表系统。
img 年代
最早网站中使用的所有的图标都是通过 img
进行实现,但随着项目的复杂,需要的图标越来越多,网站中会出现越来越多的图片请求,这严重影响了网站的加载性能。
后来出现了 image sprite
雪碧图技术,即把多张图片合成一张图片,然后利用 css
的 background-position
定位配合 overflow:hidden
来显示不同的图标。
雪碧图出现大大减少了图片的请求量,但增加了开发的复杂度,例如每次使用图标需要测量位置,新增图标需要修改雪碧图等。
iconfont 年代
网站中使用的某些图标相对比较简单,因此大佬们寻求将简单的图标设计成文字格式,即图标本质是文字,我们只需要按照引入文字的方式引入图标即可。
iconfont
字体图标也有三种使用方法:
- 基于
unicode
模式:unicode
模式大家肯定非常熟悉,大致是下面这样的流程:
1. @font-face 引入自定义字体
2. 定义使用iconfont的样式
3. 使用 i 图标,然后传入对应的图标编码
<i class="iconfont"></i>
这种实现方式最大的缺点是编码部分 
,使用编码的方式非常不直观,语义也比较差。
- 基于
font-class
: 图标编码格式使用起来非常不直观,因此大佬们将这些编码提前封装好,整合在css
文件中,使用模式就变成了下述情况。
1. 引入对应 css 文件 font.css
2. 通过类名使用: <i class="iconfont icon-xxx"></i>
- 当前主流模式:
svg-icon
模式
上面两种使用起来都难免有自己的缺点,svg
格式出现了,svg
不仅兼容了 font
方式的优点,还具备独特的优势:
svg
是矢量图,缩放不会发生失真- 支持多色图标(上面两种方式不支持)
- 可以很精细的控制
svg
图标的每一部分 - ...
svg
方式来实现 icon
图标非常便捷,逐渐成为图标的主流方案。那 vue
项目中如何便捷舒适的使用 svg-icon
呐?别急,本文给你慢慢道来。
另外,这个世界已经悄然发生变化,现在根本无需写任何前端代码,直接使用卡拉云 —— 新一代低代码开发工具帮你搭建后台工具,卡拉云可一键接入常见数据库及 API
,无需懂前端,内置完善的各类前端组件,无需调试,拖拽即用。原来三天的开发工作量,使用卡拉云后可缩减至 1 小时,欢迎免费试用卡拉云。

调试 Vue 太麻烦?
第一步: 安装 CLI 及创建项目
首先我们需要通过 npm
或者 yarn
安装 vue-cli
工具,用于创建我们的 vue
项目。然后检查是否安装成功。
npm install -g @vue/cli
vue --version
C:\Users\xxx>vue --version
@vue/cli 5.0.3
接着我们使用 vue
命令来创建 vue
项目。
在 vue
开发中,手动配置无疑是非常复杂的,vue
官方提供了 Vue-CLI
可以让你非常友好快捷的配置你所需要的项目模板。Vue-CLI
提供了命令行交互方式,可自由的选择所需要项目配置配置。
首先进入需要创建 vue
项目的目录,运行下面的创建命令:
vue create kalacloud-svg-vue
上面的命令是创建 vue
项目的起始命令,执行完毕后,会进入第一个交互页面:
? Please pick a preset: (Use arrow keys)
Default ([Vue 3] babel, eslint)
> Default ([Vue 2] babel, eslint)
Manually select features
等待项目安装完毕后,使用 cd
命令进入项目目录,然后启动当前应用程序:
cd kalacloud-svg-vue
npm run serve
项目成功运行后,你可以在浏览器中访问 http://localhost:8080/
,你将会看到 Vue
初始项目的页面。
第二步:svg-sprite-loader 使用
在 Vue
项目中安装 svg-sprite-loader
依赖。安装成功后,你可以在 package.json
看到 svg-sprite-loader
及其版本信息。
npm install svg-sprite-loader --save-dev
在项目的 src
目录下新建 src/icons/svg
目录,存放项目所使用的所有图标 svg
文件。
修改配置文件 vue.config.js
,使得 src/icons
目录下的 .svg
使用 svg-sprite-loader
来解析。
在 vue-config.js
中添加下面配置:
const path = require("path");
function resolve(dir) {
return path.join(__dirname, "./", dir);
}
module.exports = {
chainWebpack(config) {
config.module.rule("svg").exclude.add(resolve("src/icons")).end();
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();
},
};
删除 Vue
初始化项目创建的多余代码,在项目中创建组件 components/SvgIcon.vue
<template>
<svg class="svg-icon" aria-hidden="true">
<use :xlink:href="iconName" />
</svg>
</template>
<style>
.svg-icon {
width: 1.5em;
height: 1.5em;
}
</style>
<script>
export default {
props: {
iconClass: {
type: String,
required: true,
},
},
computed: {
iconName() {
return `#icon-${this.iconClass}`;
},
},
};
</script>
在 src/icons
目录下创建 icons
目录的入口文件 index.js
,负责所有图标文件的加载。
import Vue from "vue";
import SvgIcon from "@/components/SvgIcon";
Vue.component("svg-icon", SvgIcon);
/**
* require.context 的参数说明
* './svg' 代表要查找的文件路径
* false 代表是否查找子目录
* /\.svg$/ 代表要匹配文件的正则
*
*/
const svg = require.context("./svg", false, /\.svg$/);
const requireAll = (requireContext) =>
requireContext.keys().map(requireContext);
requireAll(svg);
如果你的项目图标文件比较多,可以对 icons
目录做更详细的划分,例如你需要在首页和详情页使用 icon
,你可以设置两个文件夹 mainSvg
,detailSvg
,然后修改一下上述 index.js
在 main.js
入口文件中 全局引入 icons
。
// main.js
import "./icons";
我们去 iconfont 图标网站下载几个 svg
图标,用来测试上面的配置是否成功。
将下载的 svg
图标放置到 src/icons/svg
目录下,这里作者下载了星星图标和收藏图标。
接下来修改 App.vue
部分代码,
<template>
<div id="app">
<div class="svg-content">
<h1>如何在 Vue 中使用 SVG icon 图标系统</h1>
<h2>
卡拉云——低代码开发工具,1 秒搭建上传后台
<svg-icon icon-class="unstar"></svg-icon>
<svg-icon icon-class="stared"></svg-icon>
</h2> // 引入下载的图标——直接通过图标名引入即可
</div>
</div>
</template>
<script>
export default {
name: 'App',
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
display: flex;
justify-content: center;
flex-direction: column;
}
.svg-content {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
margin-right: 20px;
}
</style>
到这里,我们已经成功在 vue
项目中使用 svg
图标。
第三步:SvgIcon 组件应用
上面我们创建了 SvgIcon
组件,下面我们利用这个组件来实现几个功能。
收藏与取消收藏
SvgIcon
组件接收父组件传入的 iconClass
属性,来标识当前使用的 svg
图标,因此我们可以通过修改此属性来实现图标的切换。
// stared 值来代表收藏与否,值为 true 意为收藏了,因此返回收藏的图标名 stared 即可
<template>
<div id="app">
<div class="svg-content">
<h1>如何在 Vue 中使用 SVG icon 图标系统</h1>
<h2>
卡拉云——低代码开发工具,1 秒搭建上传后台
<svg-icon :icon-class="stared ? 'stared': 'unstar'" @click.native="toggle"></svg-icon>
</h2>
</div>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
stared: false,
};
},
methods: {
toggle() {
this.stared = !this.stared;
},
},
};
</script>
svg-icon
是组件,无法检测到click
事件,因此我们可以添加.native
事件修饰符来实现对click
事件的监听。
我们实现收藏与取消收藏的功能后,我们可以在这个基础上实现些比较复杂的业务处理逻辑,比如当用户收藏后提醒用户,用户取消收藏时询问用户等。
利用 element-ui
提供的组件实现上述功能。
1: 安装 element-ui
npm i element-ui -S
2:引入 element-ui
在 main.js
中写入以下内容:
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
Vue.use(ElementUI);
3:实现功能
methods: {
toggle() {
if (this.stared) {
// 询问是否要取消收藏
this.cancelStar();
} else {
// 收藏按钮
this.stared = !this.stared;
this.$message({
message: '成功收藏卡拉云,下面开始你的使用吧',
type: 'success',
});
}
},
cancelStar() {
// element-ui 提供的 messagebox 组件
this.$confirm(
'卡拉云——低代码开发工具,1 秒搭建上传后台',
'取消卡拉云收藏',
{
distinguishCancelAndClose: true,
confirmButtonText: '确认',
cancelButtonText: '放弃修改',
}
)
.then(() => {
this.stared = !this.stared;
this.$message({
type: 'warning',
message: '取消收藏成功',
});
})
.catch(action => {
this.$message({
type: 'info',
message:
action === 'cancel'
? '未取消卡拉云收藏'
: '停留在当前页面',
});
});
},
},
在 Vue 中创建动态图标
在项目中使用图标不止可以让网站内容更丰富,图文并茂;另一面图标也会起到很好的提示作用。例如(√)暗示成功或者完成,(×)暗示失败等。
例如上图所示的三种图标:
- 没有任何提示的普通文字信息
- 带有成功(√)提示的文字信息
- 带有失败(×)提示的文字信息
我们在原有 SvgIcon
组件的基础上做扩展,新建一个 components/SvgText
组件,当前组件可以展示文字和图标信息。
// SvgText.vue 的源码如下:
<template>
<div class="msg-text-container">
<div class="text-wrap">
{{text}}
<svg-icon :iconClass="icon" class="icon-pos" v-if="isNeedIcon"></svg-icon>
</div>
</div>
</template>
<script>
export default {
props: {
text: {
type: String,
require: true,
},
icon: {
type: String,
},
isNeedIcon: {
type: Boolean,
default: true,
},
},
};
</script>
<style>
.msg-text-container {
margin: 10px 0;
}
.text-wrap {
display: inline-block;
padding: 10px 40px;
border-radius: 40px;
background-color: rgb(135, 176, 196);
color: #fff;
font-size: 24px;
position: relative;
}
.icon-pos {
position: absolute;
right: -16px;
top: 3px;
background-color: #fff;
z-index: 100;
border-radius: 50%;
}
</style>
SvgText
组件共可以接收三个参数:
text
: 标签需要展示的文字信息icon
: 标签使用的图标名称isNeedIcon
: 是否需要标签,默认为true
SvgText
是一个 Vue
组件,因此在项目中我们可以使用 v-if v-for
等渲染使用它。
将 App.vue
中修改为以下内容:
<template>
<div id="app">
<div class="svg-content">
<h1>如何在 Vue 中使用 SVG icon 图标系统</h1>
<h2>
卡拉云——低代码开发工具,1 秒搭建上传后台
<svg-icon :icon-class="stared ? 'stared': 'unstar'" @click.native="toggle"></svg-icon>
</h2>
</div>
// 支持 v-for
<div class="svg-list">
<svg-text v-for="(item,index) in kalacloud" :text="item.text" :icon="item.type" :key="index"></svg-text>
</div>
</div>
</template>
<script>
import SvgText from './components/SvgText.vue';
export default {
name: 'App',
components: {
SvgText,
},
data() {
return {
stared: false,
kalacloud: [
{ text: '极速搭建业务系统', type: 'success' },
{ text: '数十倍提升开发效率', type: 'success' },
{ text: '灵活的控件系统', type: 'success' },
{ text: '不使用卡拉云', type: 'error' },
],
};
},
methods: {
// method 方法未作改变,不重复罗列
toggle() {
},
cancelStar() {
},
},
};
</script>
<style>
.svg-list {
display: flex;
flex-direction: column;
align-items: flex-start;
}
</style>
通过上图可以发现,我们成功把 kalacloud
数组的数据渲染成带图标的标签信息。
我们还可以继续做扩展,例如支持标签的删除和插入等,这部分本文就不做扩展了,有想法的小伙伴可以继续实现。
SVG icon 图标系统总结
文章系统的介绍了 svg-icon
模式在 vue
项目中的使用。如果你已经系统的实现了一遍,你会发现在 vue
中使用 svg
图标主要有以下要点:
- 配置
svg-sprite-loader
插件,vue
项目可解析对应的svg
图标文件 - 创建
SvgIcon
组件,何时需要图标直接引入组件即可。(更复杂的使用同样基于SvgIcon
组件进行扩展) - 图标存储在
src/icons/
目录下,项目中直接使用图标名即可。
如果你不想处理前端问题,想轻松搭建后台工具,推荐使用卡拉云,开发者完全不用处理任何前端问题,只需简单拖拽,即可快速生成所需组件,可一键接入包括 MySQL 在内的常见数据库及 API,根据引导简单几步打通前后端,数周的开发时间,缩短至 1 小时。
上面为使用卡拉云 10 分钟内搭建的「天气预报数据看板」,简单拖拽,几行代码即可快速完成,搭建即发布,可一键分享给其他同学一起使用。立即注册使用卡拉云。
扩展阅读: