一、講原理svg-sprite,和css-sprite有點像,就是先把所有的svg圖放頁面上,但是不現實,用的時候去取。
這個時候去MDN補一下知識。Symbol這個不是es6里的那個新增的數據類型,而是SVG中的一個標簽https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/symbol
官方說法:
symbol
元素用來定義一個圖形模板對象,它可以用一個<use>
元素實例化。symbol
元素對圖形的作用是在同一文檔中多次使用,添加結構和語義。結構豐富的文檔可以更生動地呈現出來,類似講演稿或盲文,從而提升了可訪問性。注意,一個symbol
元素本身是不呈現的。只有symbol
元素的實例(亦即,一個引用了symbol
的 <use>
元素)才能呈現。
聯系一下我剛才說的svg-sprite你就知道了,就是我們要把我們所有svg的單個放到這個標簽里,然后再起個ID,用的時候一找這個id就出來。非常完美。原理還有更有深度的東西可以自己百度去吧。
那我們要用時候不能挨個寫標簽,挨個放進去吧,那就太麻煩了,所有用這個插件svg-sprite-loader,我們只需要准備下svg圖,然后起個好記的名字。然后svg是美工給你的,所以你只需要改名字。。為了就是這個,要不誰用他
npm install svg-sprite-loader --save-dev
接下來在vue.config.js里加這些東西。上代碼
先找到這個位置
這個位置是配置webpack額外配置的,因為vue-cli3已經幫你配置好了,但是對於這需求各種變的年代。不改是不可能的,還不如在webpack里配置呢。。吐槽一下。接下來就把下邊這些代碼放進去
const svgRule = config.module.rule('svg');
// 清除已有的所有 loader。
// 如果你不這樣做,接下來的 loader 會附加在該規則現有的 loader 之后。
svgRule.uses.clear();
svgRule
.test(/\.svg$/)
.include.add(path.resolve(__dirname, './src/icons/svg'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
});
const fileRule = config.module.rule('file');
fileRule.uses.clear();
fileRule
.test(/\.svg$/)
.exclude.add(path.resolve(__dirname, './src/icons/svg'))
.end()
.use('file-loader')
.loader('file-loader');
你不要納悶,為啥配置這svg的規則又配置了下file,這個就是坑。
來先看一下package.json
這個開發依賴也沒有file-loader啊,配置他干嘛。。我就為了這個都哭,看着沒有,實際上有,就是這些vue/cli的某個的以來還是用的是file-loader所以你要是不配置的話,就會有兩個東西去處理你的svg,文件。他會告訴你需要你一個loader,實際上你有倆。
此時按我這個配置就可以了。為了證明有,你看看這個。。
然后自己寫個組件。,再用webpack的
require.context方法把那些svg導入進來。這個方法作用就是把所有的svg億import形式引入進來。
看代碼
先看組件
<template>
<svg :class="svgClass" xmlns="http://www.w3.org/2000/svg">
<use :xlink:href="iconName" xmlns:xlink="http://www.w3.org/1999/xlink" />
</svg>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
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>
用的時候就是icon-class里的就是svg你開始的命名,別整中文啊。后邊這個class-name就是你自定義的class,要設置大小記得font-size可別width,height啥的。。那就很尷尬了
<svg-icon icon-class="copy" class-name="size"></svg-icon>
接下來就是如何引入的svg的進入頁面的
import Vue from 'vue';
import SvgIcon from '@/components/SvgIcon'; // svg組件
// register globally
Vue.component('svg-icon', SvgIcon);
const req = require.context('./svg', false, /\.svg$/);
const requireAll = requireContext => requireContext.keys().map(requireContext);
requireAll(req);
先把組件全局注冊,然后引入組件;
如果看不懂就直接百度require.context然后你就懂了。
這個時候再去main.js里引入就好了。(別忘了這一步)
import './icons'; // icon
你就可以用了,而且是頁面各個角度的用。你要看一下dom結構有沒有這個。
有你就大膽用吧,啥毛病沒有,沒有的話,是不是你svg名字給寫錯了。其他都沒錯了還是不顯示就去檢查這個webpack的配置吧和控制台的錯誤輸出。其他就只有碰到了才清楚。
現在最新版給的方法是這個(先別急着用)
1.在對應vue項目里添加插件
vue add svg-sprite
2.再執行:
npm install svgo svgo-loader --save-dev
這里開發以來會增加一個vue-cli-svg-sprite和svgo和svgo-loader
因為svgo可以整理svg的某些東西,去掉或者增加,反正是可以批量處理他們,以方便我們使用。他會給我們自動生成一個已經寫好的組件 到時候你引入這個組件就可以了。我的情況就是沒找到原因就是一直不顯示還不報錯。so,我拋棄了他,使用了上邊的方法,實際上vue-cli-svg-sprite的依賴也是svg-sprite-loader,沒准問題也是file-loader的事,應該是我的某些配置問題。如果有大神知道原因,希望你告訴我一下吧。最近沒空去探尋真理,實現了先用。