
直接引入SVG:新手最易上手的基础方案
直接引入SVG绝对是新手友好度最高的方案——不用配置任何工具,不用学复杂语法,只要会写Vue组件就能做。我先给你拆两种最常见的方式:引入SVG文件和写inline代码。
先讲「引入SVG文件」:比如你在src/assets/icons
里放了个home.svg
,想在Home.vue
里用,直接在组件里写import HomeIcon from '@/assets/icons/home.svg'
,然后在模板里用
就行。是不是超简单?我去年帮楼下奶茶店做小程序的时候,就用这招——他们就5个图标,直接引入用了半天就做完了,老板还夸我快。
再讲「inline SVG」:就是把SVG代码直接复制到Vue组件的模板里。比如你要加个搜索图标,直接复制进去。这种方式的优点是「所见即所得」,改颜色直接改
path
的fill
属性就行;但缺点也很明显——如果有10个组件用这个图标,改颜色得改10次,后期维护简直崩溃。
我之前有个读者,刚学Vue时用inline SVG做了个个人博客,里面有10个图标。后来他想把所有图标改成蓝色,结果改了俩小时还漏了footer里的图标,最后来找我吐槽。我告诉他:直接引入适合小项目(图标<20个),比如个人博客、小型工具类应用,快准狠;但图标多了,一定要换更高效的方案。
封装SVG组件:中项目的高效管理方案
当你的项目有20-50个图标时,直接引入的「代码混乱」问题会彻底爆发——比如设计师改了某个图标的颜色,你得打开10个组件找对应的SVG代码;或者想换个图标,得逐个文件替换。这时候,封装成可复用组件就是解决问题的关键。
封装组件的核心逻辑是「用props传递参数」——把图标名称、颜色、大小做成可配置项,这样改的时候只需要调组件的props,不用改每个使用的地方。我给你演示一个基础的SvgIcon
组件写法:
width="size"
height="size"
fill="color"
class="svg-icon"
>
<!-
用use标签引用雪碧图的symbol(后面会讲雪碧图) >
<use xlink:href="#icon-${name}
">
export default {
name: 'SvgIcon',
props: {
// 图标名称(对应SVG文件的名字)
name: {
type: String,
required: true
},
// 图标颜色
color: {
type: String,
default: '#333' // 默认深灰色
},
// 图标大小(单位:px)
size: {
type: Number,
default: 24 // 主流图标尺寸
}
}
}
.svg-icon {
cursor: pointer;
transition: fill 0.3s;
}
.svg-icon:hover {
fill: #ff6600; // hover时变橙色,统一交互
}
写好组件后,用的时候只需要写——是不是超简洁?我之前做一个电商项目时,图标有50多个,封装后设计师改颜色,我只需要把组件的
color
默认值改成#2196F3
(谷歌蓝),全项目的图标都同步变了,省了我整整一天的时间。
封装组件还有个隐藏优势:统一交互逻辑。比如我在组件里加了hover
变颜色的样式,所有用SvgIcon
的图标都会有这个效果,不用每个组件单独写CSS。再比如想加「点击图标震动」的动画,只需要在组件里加个@click
事件和animation
样式,全项目都能用——这就是组件化的力量。
不过封装组件也有「小麻烦」:如果你的图标是用svg-sprite-loader
生成的雪碧图(后面会讲),得调整组件里的use
标签写法;如果是直接引入文件,得把use
换成img
标签,用require
引入文件。比如直接引入文件的组件写法:
src="iconUrl"
alt="name"
style="{ width: size + 'px', height: size + 'px', fill: color }"
/>
export default {
name: 'SvgIcon',
props: { / 和之前一样 / },
computed: {
iconUrl() {
// 动态引入SVG文件
return require(@/assets/icons/${this.name}.svg
)
}
}
}
这种写法适合没配置svg-sprite-loader
的项目,缺点是「每个图标发一个请求」,但胜在简单。
用svg-sprite-loader:大项目的性能优化方案
当你的项目有50个以上图标时,封装组件能解决「管理问题」,但「性能问题」会凸显——50个图标就是50个HTTP请求,每个请求哪怕10ms,也得500ms加载时间,移动端可能更慢。这时候,svg-sprite-loader就是救星——它能把所有SVG合并成一个「雪碧图」,只发一个请求,彻底解决请求数过多的问题。
先讲原理:雪碧图怎么工作?
svg-sprite-loader
会把每个SVG文件转换成一个标签(比如
icon-home.svg
会变成...
),然后把所有symbol
装进一个标签里,作为「雪碧图」插入到页面的
中。使用时,只需要用
就能引用对应的
symbol
——相当于从雪碧图里「裁剪」出对应的图标。
配置步骤(Vue CLI 4为例)
npm install svg-sprite-loader save-dev
(或yarn add svg-sprite-loader -D
)。vue.config.js
:Vue CLI用chainWebpack
配置webpack规则,我们需要「清除默认的SVG处理规则」,再「添加svg-sprite-loader
的规则」。代码如下: javascript
const path = require('path')
module.exports = {
chainWebpack(config) {
//
config.module.rules.delete('svg')
//
config.module
.rule('svg-sprite') // 规则名称
.test(/.svg$/) // 匹配.svg文件
.include.add(path.resolve(__dirname, 'src/assets/icons')) // 只处理src/assets/icons目录下的SVG
.end()
.use('svg-sprite-loader') // 使用svg-sprite-loader
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]' // 生成的symbol id格式:icon-文件名
})
}
}
里用
require.context批量引入
src/assets/icons下的SVG(不用逐个import):
javascript
const req = require.context('@/assets/icons', false, /.svg$/)
req.keys().forEach(req) // 自动引入所有.svg文件
组件(或直接写
use标签):
vue
<!-
<!-
为什么说这是大项目的「终极优化」?
我去年帮一个教育类项目做优化时,用svg-sprite-loader把50个图标合并成一个雪碧图,页面加载时间从3秒降到1.5秒——谷歌PageSpeed Insights评分直接从60涨到85。减少请求数是前端性能优化的核心指标之一,而
svg-sprite-loader正好命中这个点。
注意事项:避开这些坑
里的路径要和你的SVG存放目录一致。我之前有个读者把
src/assets/icons写成
src/icon,结果loader没找到文件,找了半小时才发现问题。
要限定在自己的SVG目录,否则
node_modules里的SVG(比如第三方组件的图标)会被误处理。
标签引用雪碧图,解决办法是引入
svg4everybody polyfill——在
index.html里加
,就能让IE11支持。
用Vue插件全局调用:大项目的终极便捷方案
当你的项目有100个以上图标,且分布在多个模块时,「每次用SvgIcon都要
import」会变成负担——比如写个
Header组件要
import SvgIcon,写个
Footer组件还要
import,重复劳动太烦。这时候,Vue插件就能解决「重复引入」的问题——把
SvgIcon注册成全局组件,不用
import就能用。
写一个简单的Vue插件
下新建
svgIconPlugin.js:
javascript
import SvgIcon from '@/components/SvgIcon.vue'
export default {
install(Vue) {
// 注册全局组件
Vue.component('SvgIcon', SvgIcon)
}
}
里使用插件
: javascript
import Vue from 'vue'
import svgIconPlugin from './plugins/svgIconPlugin'
Vue.use(svgIconPlugin)
这样,所有Vue组件里都能直接写,不用再
import了!我之前做企业级后台管理系统时,100多个图标用了插件后,开发效率提高了30%——以前每个组件都要写
import SvgIcon from '@/components/SvgIcon',现在直接写标签就行。
第三方插件更省心
如果你不想自己写插件,可以用vue-svg-icon这样的第三方库——它已经帮你封装好了插件,还支持动态加载、自定义样式。安装步骤:
里引入:
javascript
import Vue from 'vue'
import SvgIcon from 'vue-svg-icon/Icon'
Vue.component('svg-icon', SvgIcon)
第三方插件的优点是「省时间」,缺点是「版本兼容性」——比如我之前用vue-svg-icon时,Vue版本是2.6,插件支持;后来升级到Vue 3,插件没及时更新,只好自己写了个插件。
各方案对比:快速选适合你的
最后给你做个「方案对比表」,帮你10秒选对方案:
方案类型 | 适用项目规模 | 核心优点 | 核心缺点 | 推荐指数 |
---|---|---|---|---|
直接引入 | 小项目(<20图标) | 无需配置,新手友好 | 图标多了代码乱 | ★★☆☆☆ |
封装组件 | 中项目(20-50图标) | 组件化管理,易维护 | 需手动引入组件 | ★★★☆☆ |
svg-sprite-loader | 大项目(>50图标) | 合并雪碧图,减少请求 | 需配置webpack | ★★★★☆ |
Vue插件全局调用 | 大项目(>100图标) | 全局可用,不用引入 |