如何在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的方法,我能想到的就这么多,如果大家有更好的方法,欢迎留言讨论。
1. 本站所有文章教程及资源素材均来源于网络与用户分享或为本站原创,仅限用于学习和研究。
2. 如果内容损害你的权益请联系客服QQ:1642748312给予处理。
码云笔记 » 如何在vue项目中配置使用svg呢