如何在vue项目中引入svg图标

概述

svg,即Scalable Vector Graphics,可缩放矢量图形。

相对于jpg,png图标,svg可以在任意分辨率下保证不会模糊,即便是网页缩放了。

在这里插入图片描述
上图是知乎的截图,可以看到铃铛图标是svg的,消息数量是CSS写的,二者缩放到任意体积都可以保持一个同等的清晰度。

而且现在很多ui标注的软件都已经支持直接生成svg,比如sketch,那为何不尝试一下呢。

配置

svg是一种用xml描述的语言,也就是说,html中引入svg,是以嵌入xml的方式进行的。(也有其他的多种方式,比如img直接引入)
在这里插入图片描述
如上,比如circle标签表示圆,和html是很相似的,只是其用于描述各种图形。

基于此,在vue项目中,我们完全可以将上面的标签封装成一个组件。这样想用的地方直接引入就可以了。

<!-- svg-icon 组件 -->
<template>
	<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
	   <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
	</svg> 
</template>

似乎没什么问题,但我们的svg并非自己画出来的,而是ui大佬们给出的svg图标,所以这时候我们就需要svg中另一个标签 use,这个标签的意思是以id的形式使用某个具体的svg, 比如:

<svg viewBox="0 0 30 10" xmlns="http://www.w3.org/2000/svg">
  <circle id="myCircle" cx="5" cy="5" r="4" stroke="blue"/>
  <use href="#myCircle" x="10" fill="blue"/>
</svg>

在这里插入图片描述
可以看出use相当于拷贝了一份新的出来,并且还可以覆盖原有的样式。

利用这样一个功能,我们就可以实现一个类似雪碧图的加载svg方式:

在页面中预先加载所有的svg,然后再需要的具体某个svg的地方使用id的方式定位到所需的具体的svg

这个思路不是我发明的,而是参考了以下:

Sprites are rendered and injected in pages automatically, you just refer to images via <svg><use xlink:href="#id"></use></svg>

这个正是svg-sprite-loader中的描述。也就是在webpack中实现引入svg图标所需要的loader。

好了,既然有这个思路,不妨改造一下上面写过的组件:

<template>
  <svg v-on="$listeners">
    <use :xlink:href="iconName" />
  </svg>
</template>

<script>
export default {
  name: 'SvgIcon',
  props: {
    iconName: {
      type: String,
      required: true,
    }
  },
  ....

在需要引入的地方引入:

<svg-icon  iconName="my-svg-icon" />

并修改vue.config.js的配置

chainWebpack: (config) => {
...
    config.module
      .rule('svg')
      .exclude.add(resolve('src/assets/icons'))
      .end();
    config.module
      .rule('icons')
      .test(/\.svg$/)
      .include.add(resolve('src/assets/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .end();
}

简单说明一下以上的配置,vue-cli已经会处理svg了,但并不是以雪碧图的方式引入的。这里我们自己配置单独处理,所以先移除原有的规则,并添加自己的规则。

到这里,我们已经实现了自定义的组件,配置好了loader,但svg文件还没有引入的,我们希望的引入方式是全部引入(就像雪碧图),然后在页面加载时候加载,需要使用的地方直接标明ID即可。

所以还需要写一个加载所有svg文件的js文件,当然这里不希望挨个svg去import,而是自动的引入某一个文件夹下的所有svg文件。webpack恰恰提供了这样一个api require.context,这里不详细介绍了,有兴趣的可以自行了解。只是放出最终的代码

import Vue from 'vue';
import SvgIcon from '@/components/svgIcon';

Vue.component('svg-icon', SvgIcon);

const req = require.context('./svg', false, /\.svg$/);
const requireAll = (requireContext) => requireContext.keys().map(requireContext);
requireAll(req);

简单说明一下,该文件配合svg-sprite-loader会生成一个以文件名为svg id的雪碧图。所以使用svg-icon这个组件的时候,iconName应该与svg的文件名保持一致。当然这个可以配置,具体详见svg-sprite-loader的文档。

至此,所以需要的配置都以就绪,尽情页面中使用吧…

参考

https://www.npmjs.com/package/svg-sprite-loader
https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值