如何在vue项目中配置使用svg呢

日常使用 svg 作为图标使用已经很常见了,以下为几种使用方式。
file-loader 解析资源文件
最原始的无非就是直接导入使用了 , webpack 使用了file-loader 对所有静态资源进行路径解析,包括图片、字体、文件等。
简单的配置对.svg 的解析:
module.exports = {
module: {
rules: [
{
test: /\.(svg)(\?.*)?$/,
use: [
{
loader: 'file-loader',
options: {
name: 'img/[name].[hash:8].[ext]',
},
},
],
},
],
},
};
filer-loader 可以解析import/require() 文件路径,并把文件输出到构建目录中,然后在组件文件中使用导入的资源。
<template>
<div>
<img :src="icon404" />
<!-- <object :data="icon404"></object>
<iframe :src="icon404"></iframe> -->
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
// import icon404 from "@/assets/icons/404.svg";
const icon404 = require("@/assets/images/icon-404.svg");
interface IState {
description: string;
}
@Component({
name: "work-bench",
})
export default class extends Vue implements IState {
description = "展示当前项目拥有的组件,数据皆为模拟测试数据.";
// 实例中定义引用
icon404 = icon404;
}
</script>
通过img \ object \ iframe 作为资源载体加载资源 . 这样引入的方式对于我们常用修改颜色、字号等产生很大不便,组件中资源过多就存在大量的import 。
可以通过打印查看icon404 的值是什么? 是对引用的当前.svg资源的路径地址。
svg-sprite-loader 声明式调用
为什么说是声明式调用 , 因为它将我们需要的 svg 资源作为一个模版变量,进而进行指向引用即可。
首先我们按照 npm 包文档指引进行配置。
安装
# 或 yarn npm install svg-sprite-loader -D
webpack 简单配置
变更了 loader 为svg-sprite-loader:
module.exports = {
module: {
rules: [
{
test: /\.(svg)(\?.*)?$/,
use: [
{
loader: 'svg-sprite-loader',
options: {
symbolId: "icon-[name]",
},
},
],
},
],
},
};
现在在看组件内的.svg 引入,已经加载不出来了,这里要注意的是require 导入。
// ... 访问导入的值 this.icon404 = icon404.default;
通过 svg 标签use 呈现
通过打印查看导入的内容 icon404
<symbol xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 400" id="icon-icon-404"> // ... svg 内容 </sysmbol>
提供了id 作为引用键值 . 再使用img \ object 不行了,了解过 svg 基础知识的同学知道,symbol 用来定义一个图形模版,然后使用use 呈现。
svg-sprite-loader 会将加载的 svg 定义成symbol 汇聚到一个<svg> 元素中添加到 body 中。
这样的话,我们局部定义 svg 引用对应的symbol,通过use标签引用资源。
导入的icon404 是一个SpriteSymbol<id,viewBox,content>实例, 通过id 进行访问。
<template>
<div>
<svg>
<use :xlink:href="`#${icon404.id}`" />
</svg>
</div>
</template>
当我们知道了 svg 的名称之后,加上 webpack 的配置symbolId: "icon-[name]",就不需要使用icon404 对象了,只需要导入。
<template>
<div>
<svg>
<use :xlink:href="#icon-icon-404" />
</svg>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
// import icon404 from "@/assets/icons/404.svg";
// const icon404 = require("@/assets/images/icon-404.svg");
// 直接导入资源
import "@/assets/icons/404.svg";
interface IState {
description: string;
}
@Component({
name: "work-bench",
})
export default class extends Vue implements IState {
description = "展示当前项目拥有的组件,数据皆为模拟测试数据.";
// 此处已不再需要定义实例中的变量
// icon404 = icon404.default;
}
</script>
就可以愉快的使用啦,这样还存在一个问题就是,每个需要使用的组件都需要导入 ,而且这明显可以作为一个模版抽离出来进行组件化使用。
批量处理 svg
按照上面的思路,我们可以定一个index.ts ,导入所有的 svg 图片,然后导出。
// 引入一遍所有的 svg 图标 import '@/assets/images/icon-404.svg' import '@/assets/images/icon-404.svg' import '@/assets/images/icon-404.svg' import '@/assets/images/icon-404.svg' // ... 更多
记得要在主入口文件main.ts 引入。
// icon-svg import "@/components/svgIcon/index.ts";
这样在所有 vue 组件中使用,不需要每次都导入了 svg 了。
当我们在多个组件中使用某一代码段时,我们就想把它抽离成组件,定一个svgIcon.vue ,这样的:
<template>
<svg :class="svgClass" v-on="$listeners">
<use :xlink:href="svgName" />
</svg>
</template>
<script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator";
@Component({
name: "svg-icon",
})
export default class extends Vue {
@Prop() /* 图标名称 */ readonly iconName!: string;
@Prop({ default: "" }) /* 图标类名 */ readonly iconClass?: string;
// 我们配置的 loader 选项中,定义了 icon-[name]
get svgName() {
return `#icon-${this.iconName}`;
}
get svgClass() {
return `svg-icon ${this.iconClass}`;
}
}
</script>
<style lang="less" scoped>
.svg-icon {
width: 1em;
height: 1em;
fill: currentColor;
overflow: hidden;
}
</style>
包含了 svg 名称 , 内部处理引入的sysmbolId 。使用的人只需要知道 svg 名称是什么就行了。 不关注 webpack 配置,还可以加上自定义 class 名,以及原生事件等等。
注册为全局组件。在index.ts 调整:
import Vue from "vue";
import SvgIcon from "./index.vue";
// 引入一遍所有的 svg 图标
import '@/assets/images/icon-404.svg'
import '@/assets/images/icon-404.svg'
import '@/assets/images/icon-404.svg'
import '@/assets/images/icon-404.svg'
// ... 更多
// SVG 图标
Vue.component("svg-icon", SvgIcon);
然后就可以在所所有的组件中愉快的使用公共组件svg-icon 了,不需要每次都导入,
怎么使用呢?还是上面的组件。
<template>
<div>
<!--<svg>
<use :xlink:href="#icon-icon-404" />
</svg>-->
<!-- 正常使用一个 vue 组件 -->
<svg-icon iconName="icon-404"></svg-icon>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
// 导入不需要
// import icon404 from "@/assets/icons/404.svg";
// const icon404 = require("@/assets/images/icon-404.svg");
interface IState {
description: string;
}
@Component({
name: "work-bench",
})
export default class extends Vue implements IState {
description = "展示当前项目拥有的组件,数据皆为模拟测试数据.";
// 不需要
// icon404 = icon404.default;
}
</script>
是不是很完美 ,还需要优化的点就是加载 svg 资源的,我们只不过是换了个地方import。
// 引入一遍所有的 svg 图标 import '@/assets/images/icon-404.svg' // 成百上千个 ....
想办法批量加载完成 ,幸好 webpack 提供了一个 API 用于做批量加载的事情。 传送门
require.context 引入指定文件夹下的所有文件:
require.context(dir,useSubDir,regExp,mode)
dir:需要加载的目录路径;useSubDir:是否需要搜索其他子目录;regExp:加载匹配文件的正则表达式;mode:加载方式mode=sync。
返回一个 require 函数,可以接受一个 request 参数 ;
require 函数三个静态属性resolve,keys,id ,通过编译属性kyes 执行每一个加载资源的请求。
// 指定目录加载所有的.svg 资源
const req = require.context("@/assets/images", false, /\.svg$/);
// 编译 req 属性的 keys , 对每一个资源路径执行加载函数
req.keys().forEach(req)
然后我们的index.ts 文件就修改为:
import Vue from "vue";
import SvgIcon from "./index.vue";
// import "@/assets/images/icon-404.svg";
// SVG 图标
Vue.component("svg-icon", SvgIcon);
const req = require.context("@/assets/images", false, /\.svg$/);
req.keys().forEach(req)
看起来就简洁多了, 你只需要往这个目录添加你想要使用的 svg 资源就行了, 然后在项目中使用它.
vue.config.js 配置
上面简单的自定义 webpack 配置时,如何配置 webpack,通常我们都使用了vue-cli 脚手架搭建 vue 项目。
那就要在vue.config.js 中调整 loader 配置了:
// vue.config.js
// eslint-disable-next-line
const path = require("path");
module.exports ={
chainWebpack: (config) => {
// svg-sprite-loader
config.module.rules.delete("svg");
config.module
.rule("svg-sprite-loader")
.test(/\.svg$/)
.include.add(path.join(__dirname, "./src/assets/icons"))
.end()
.use("svg-sprite-loader")
.loader("svg-sprite-loader")
.options({ symbolId: "icon-[name]" });
}
}
首先,移除了.svg 的默认 loader 规则配置,开始添加针对.svg 文件的 loader 规则配置。
关于vue.config.js 配置详解,还会有另一篇文章来说明,解析chainWebpack是如何运转的。
svgo-loader 优化 svg
svgo-loader依赖安装svgo ,用来优化 svg 资源,清理掉多余、不必要的信息,比如:元数据信息、批注信息、隐藏的元素等。
还有用来操作 svg,svgo 可以转换 svgSVG-as-XML SVG-as-JS AST 树从而手动新增、更新、删减元素。
{
content: [
{
doctype:'',
},
{
comment:'',
},
{
elem: 'svg',
local: 'svg',
attrs: {
// ...
},
content:[
{
// ... 嵌套子元素
}
]
}
]
}
需要更详细操作 svg 的可以自行去查看这个库,没怎么具体使用过。如果有这方面的需求,肯定还有有更细致的文章。
了解过之后,再来看svgo-loader。
安装
npm install svgo-loader --save-dev
webpack 配置
简单的配置,需要明确的是它不是file-loader \ svg-sprite-loader 的替代,作用不一样。
起一个中间优化的作用,配置中添加svgo-loader 即可。
module.exports = {
module: {
rules: [
{
test: /\.(svg)(\?.*)?$/,
use: [
{
loader: 'file-loader',
options: {
name: 'img/[name].[hash:8].[ext]',
},
},
{
loader:"svgo-loader"
}
],
},
],
},
};
vue.config.js 配置
在之前配置的svg-sprite-loader 追加 loader 配置即可。
// vue.config.js
// eslint-disable-next-line
const path = require("path");
module.exports ={
chainWebpack: (config) => {
// svg-sprite-loader
config.module.rules.delete("svg");
config.module
.rule("svg-sprite-loader")
.test(/\.svg$/)
.include.add(path.join(__dirname, "./src/assets/icons"))
.end()
.use("svg-sprite-loader")
.loader("svg-sprite-loader")
.options({ symbolId: "icon-[name]" })
.end()
.use("svgo-loader")
.loader("svgo-loader");
}
}
最后
以上就是今天为大家分享的如何在 vue 项目中配置使用 svg 的方法,我能想到的就这么多,如果大家有更好的方法,欢迎留言讨论。
以上关于如何在vue项目中配置使用svg呢的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » 如何在vue项目中配置使用svg呢

微信
支付宝