vue項(xiàng)目中自動(dòng)導(dǎo)入svg并愉快的使用方式
引入圖標(biāo)的幾種方式
遠(yuǎn)古時(shí)代
- 一個(gè)個(gè)小圖標(biāo)png圖片引入,代碼中在一個(gè)個(gè)引用
- spirit圖片,將多個(gè)圖標(biāo)放在一張png圖片上,通過background屬性顯示對(duì)應(yīng)的圖標(biāo)
iconfont時(shí)代
- 將整個(gè)工程用到的圖標(biāo),全部打包生成字體文件,在代碼中全局引入,只要通過標(biāo)簽和class就能夠使用
缺點(diǎn):
- 當(dāng)新增圖標(biāo)的時(shí)候,需要重新生成字體文件,當(dāng)團(tuán)隊(duì)開發(fā)的時(shí)候,新增圖標(biāo)就顯得格外麻煩
svg時(shí)代
優(yōu)勢(shì):
- svg可以單獨(dú)引入,不需要像iconfont一起打包
- 封裝一個(gè)全局組件,就能像iconfont一樣,傳入class名稱就能顯示對(duì)應(yīng)svg圖標(biāo)
注意點(diǎn):svg有兼容性問題,使用的時(shí)候先跟產(chǎn)品談?wù)撉宄枨笫欠裥枰嫒輎e
處理loader,對(duì)指定目錄svg文件處理
安裝loader
npm i svg-sprite-loader -D
配置vue.config.js
這里推薦一個(gè)vue指令,可以方便的查詢vue隱藏的配置文件的loader規(guī)則
vue inspect --rule svg
接下來上配置文件
找到vue.config.js 如果沒有就新建一個(gè)
const path = require("path");
// 引入path模塊
const resolve = dir => path.join(__dirname, dir);
module.exports = {
? ...,
? // 配置路徑別名
? chainWebpack: config => {
? ? // vue inspect --rule svg ?// 使用以上指令,可以獲取vue配置的loader規(guī)則
? ? // svg loader 取消src/icons目錄下的處理
? ? config.module.rule("svg").exclude.add(resolve("src/icons"));
? ? // 添加自定義loader規(guī)則 icons,只處理src/icons目錄
? ? config.module
? ? ? .rule("icons")
? ? ? .test(/\.svg$/)
? ? ? .include.add(resolve("src/icons")) // 上下文變化
? ? ? .end() // 返回上下文
? ? ? .use("svg-sprite-loader")
? ? ? .loader("svg-sprite-loader")
? ? ? .options({ symbolId: "icon-[name]" });
? },
? ...
};主要有以下幾點(diǎn):
- 將svg默認(rèn)規(guī)則繞開我們自定義的目錄 src/icons
- 創(chuàng)建自定義規(guī)則icons,包含我們的自定義目錄src/icons
- 配置svg使用名稱規(guī)則, icon-[文件名]
接下來使用vue inspect看下目前的配置
vue inspect --rule svg
/* 以下是我們修改后的svg loader規(guī)則 */
/* config.module.rule('svg') */
{
? test: /\.(svg)(\?.*)?$/,
? exclude: [
? ? '/Users/{UserName}/project/src/icons' /* 這個(gè)是不包含的目錄 */
? ],
? use: [
? ? /* config.module.rule('svg').use('file-loader') */
? ? {
? ? ? loader: '/Users/{UserName}/project/node_modules/file-loader/dist/cjs.js',
? ? ? options: {
? ? ? ? name: 'img/[name].[hash:8].[ext]'
? ? ? }
? ? }
? ]
}vue inspect --rule icons
// 以下是我們添加的icons loader規(guī)則
/* config.module.rule('icons') */
{
? test: /\.svg$/,
? include: [
? ? '/Users/{UserName}/project/src/icons' /* 這個(gè)是包含的目錄 */
? ],
? use: [
? ? /* config.module.rule('icons').use('svg-sprite-loader') */
? ? {
? ? ? loader: 'svg-sprite-loader',
? ? ? options: {
? ? ? ? symbolId: 'icon-[name]'
? ? ? }
? ? }
? ]
}編寫一個(gè)自定義組件
<template> ? <svg v-on="$listeners" :class="svgClass"> ? ? <use :xlink:href="iconName" rel="external nofollow" ></use> ? </svg> </template>
<script>
export default {
? name: "SvgIcon",
? props: {
? ? iconClass: {
? ? ? type: String,
? ? ? default: ""
? ? },
? ? className: {
? ? ? type: String,
? ? ? default: ""
? ? }
? },
? computed: {
? ? iconName() {
? ? ? return `#icon-${this.iconClass}`;
? ? },
? ? svgClass() {
? ? ? if (this.className) {
? ? ? ? return "svg-icon " + this.className;
? ? ? } else {
? ? ? ? return "svg-icon";
? ? ? }
? ? }
? }
};
</script><style scoped>
.svg-icon {
? width: 1em;
? height: 1em;
? vertical-align: -0.15em;
? fill: currentColor;
? overflow: hidden;
}
</style>入?yún)⒂?個(gè),iconClass(圖標(biāo)的名稱)和className(自定義樣式名稱)
iconClass為src/icon下目錄的svg文件名稱
編寫一個(gè)js,實(shí)現(xiàn)svg自動(dòng)化
import Vue from "vue";
import SvgIcon from "@/components/SvgIcon.vue";
const isEnv = process.env.NODE_ENV === "development";
// 自動(dòng)加載 icons 目錄下的所有svg
const req = require.context("./svg", true, /\.svg$/);
const svgNameSet = new Set();
req.keys().map(url => {
? const pathSplit = url.split("/");
? const fileName = pathSplit[pathSplit.length - 1];
? isEnv && console.log(fileName);
? if (svgNameSet.has(fileName)) {
? ? isEnv && console.error("圖標(biāo)名稱重復(fù),請(qǐng)檢查");
? } else {
? ? svgNameSet.add(fileName);
? ? return req(url); // 可以用于異步require
? }
});
// 全局注冊(cè)SvgIcon.vue組件
Vue.component("svg-icon", SvgIcon);這個(gè)腳本主要有以下幾個(gè)內(nèi)容:
- 全局注冊(cè)SvgIcon.vue組件
- 使用require.context("./svg", true, /\.svg$/);,對(duì)src/icons目錄遞歸遍歷,獲取所有文件
- 做一遍開發(fā)環(huán)境的重復(fù)提醒(因?yàn)檫@邊使用的icon-[name],name是唯一的,所以當(dāng)有相同文件名稱的svg,會(huì)被覆蓋)
至此就可以愉快的使用svg了
使用方法如下:
- 將svg文件復(fù)制到src/icons目錄下,比如diamond.svg
- 在vue的template中直接使用 <svg-icon iconClass="diamond"></svg-icon>
是不是很簡(jiǎn)單,趕緊去試試吧
壓縮優(yōu)化
SVG通常會(huì)有一些冗余信息(如:fill=“red”, 還有可能導(dǎo)致無法修改顏色)導(dǎo)致影響體積,這里我們可以使用svgo-loader來進(jìn)一步壓縮
// install
npm i svgo-loader -D
// vue.config.js
// 接上面svg的配置
...
.end()
.use('svgo-loader')
.loader('svgo-loader')
.end()以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue實(shí)現(xiàn)動(dòng)態(tài)路由的方法及路由原理解析
這篇文章主要介紹了路由原理及vue實(shí)現(xiàn)動(dòng)態(tài)路由,Vue Router 提供了豐富的 API,可以輕松地實(shí)現(xiàn)路由功能,并支持路由參數(shù)、查詢參數(shù)、命名路由、嵌套路由等功能,可以滿足不同應(yīng)用程序的需求,需要的朋友可以參考下2023-06-06
在Vue中進(jìn)行數(shù)據(jù)分頁的實(shí)現(xiàn)方法
在前端開發(fā)中,數(shù)據(jù)分頁是一個(gè)常見的需求,特別是當(dāng)處理大量數(shù)據(jù)時(shí),Vue作為一款流行的JavaScript框架,提供了強(qiáng)大的工具和生態(tài)系統(tǒng)來實(shí)現(xiàn)數(shù)據(jù)分頁,本文將介紹如何在Vue中進(jìn)行數(shù)據(jù)分頁,以及如何設(shè)計(jì)一個(gè)通用的分頁組件,需要的朋友可以參考下2023-10-10
使用vue.js2.0 + ElementUI開發(fā)后臺(tái)管理系統(tǒng)詳細(xì)教程(一)
這篇文章主要介紹了使用vue.js2.0 + ElementUI開發(fā)后臺(tái)管理系統(tǒng)詳細(xì)教程(一)的相關(guān)資料,需要的朋友可以參考下2017-01-01
在vue中v-for循環(huán)遍歷圖片不顯示錯(cuò)誤的解決方案
這篇文章主要介紹了在vue中v-for循環(huán)遍歷圖片不顯示錯(cuò)誤的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01
vue中實(shí)現(xiàn)methods一個(gè)方法調(diào)用另外一個(gè)方法
下面小編就為大家分享一篇vue中實(shí)現(xiàn)methods一個(gè)方法調(diào)用另外一個(gè)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-02-02
一文了解Vue 3 的 generate 是這樣生成 render&n
本文介紹generate階段是如何根據(jù)javascript AST抽象語法樹生成render函數(shù)字符串的,本文中使用的vue版本為3.4.19,感興趣的朋友跟隨小編一起看看吧2024-06-06
vue treeselect獲取當(dāng)前選中項(xiàng)的label實(shí)例
這篇文章主要介紹了vue treeselect獲取當(dāng)前選中項(xiàng)的label實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-08-08
在Vue中使用Viser說明(基于AntV-G2可視化引擎)
這篇文章主要介紹了在Vue中使用Viser說明(基于AntV-G2可視化引擎),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-10-10

