1. 程式人生 > 實用技巧 >Vue企業級優雅實戰04-元件開發01-SVG圖示元件

Vue企業級優雅實戰04-元件開發01-SVG圖示元件

(後續的文章 公眾號會提前一週更新,歡迎關注文末的微信公眾號:程式設計師搞藝術) 預覽本文的實現效果:

# gitee

git clone [email protected]:cloudyly/dscloudy-admin-single.git
# github
git clone [email protected]:cloudyly/dscloudy-admin-single.git
git checkout 02_SVGIcon

本文主要描寫如何讓 Vue 工程支援 SVG 圖示,以及如何獲取 SVG 圖示。

Git 本地倉庫切換新分支:

git checkout -b 02_SVGIcon

確認分支:

git branch

1 SVG 圖示的獲取

無論是 SVG 圖示,還是 PNG 等其他格式的圖示,都可以從阿里的 iconfont 網站上搜索。網址: https://www.iconfont.cn

開啟網站後,自己註冊賬號。最簡單的使用方式,就是直接搜尋你要的圖示。舉個例子,找個主頁的圖示:

1、 在首頁搜尋框搜尋“主頁”,回車

2、 選擇需要的圖示

3、 滑鼠移動到該圖示上,點選下載樣式的按鈕

4、下載或複製該 SVG 圖示:

“複製 SVG” 不含檔案頭,需要手動新增。我的習慣是沒有 SVG 圖示時,第一次“SVG 下載”,之後建立 SVG 檔案,從已下載的 SVG 中複製檔案頭,然後點選頁面上的 “複製 SVG”,將內容貼到 建立的 SVG 檔案中。此處先下載該 svg 圖示。

該網站也可以建立專案,將你需要的圖示新增到專案中,然後一次性生成並下載。我不太喜歡這種使用方式。兩個原因:

  • 上述方式生成的 class 命名五花八門,也許不符合專案規範;

  • 專案是持續迭代的,如果你手動更新命名,迭代過程中需要新圖示,你如何疊加進去;

  • 我需要些什麼圖示我自己都不知道,在開發過程中需要什麼圖示才去搜尋下載。

2 使工程支援 SVG

2.1 安裝依賴

Vue 專案如果要使用 SVG 圖示,需要 SVG Loader。svg-sprite-loader 可以用來載入 svg:

npm install svg-sprite-loader --save-dev

2.2 配置 svg-loader

Vue-cli 3 以上的版本,對 webpack 進行了高度封裝,要對 webpack 進行配置,需要在專案根路徑下(與 src 同級)建立配置檔案:vue.config.js ,在該檔案中配置 svg loader。

vue.config.js

const path = require('path')
const resolve = dir => path.join(__dirname, dir)
module.exports = {
 chainWebpack: config => {
  const svgRule = config.module.rule('svg')
  svgRule.uses.clear()
  svgRule.test(/\.svg$/)
    .include.add(resolve('src/icons/svg'))
    .end()
    .use('svg-sprite-loader')
    .loader('svg-sprite-loader')
    .options({
    symbolId: '[name]'
    })
    .end()
  }
}
3 SVG 封裝

後面我會將自己封裝的元件庫,拆分成獨立的工程(類似 Element UI、Ant Design Vue 等),釋出 npm 或私服後,通過 npm install 進行安裝,便於複用。現在在元件庫開發階段,需要不斷迭代完善,為了方便除錯測試,故先將元件庫放在當前工程的 src/components 目錄下。

3.1 封裝元件 svg-icon

src/components 目錄下建立目錄 ds-svg-icon, 在該目錄中建立 index.vue 檔案。該元件提供兩個屬性:

屬性名型別屬性描述
class-name String 該圖示的樣式類(與 HTML 中 class 一樣)
icon String svg 圖示檔案的名稱

為了編寫方便,父元件傳遞到 svg 元件時可以省略 icon-, 在 svg-icon 中,通過計算屬性將這個字首 icon- 拼接上去。 如:圖示名稱為 icon-home.svg, 使用元件時使用:

<svg-icon :icon-name="home"></svg-icon>

src/components/ds-svg-icon/index.vue:

<template>
 <svg :class="svgClass" aria-hidden="true">
  <use :xlink:href="svgIcon"></use>
 </svg>
</template>
<script>
export default {
 name: 'ds-svg-icon',
 props: {
  icon: {
   type: String,
   required: true
   },
  className: {
   type: String,
   required: false,
   default: ''
   }
  },
 computed: {
  svgClass () {
   return `ds-svg-icon ${this.className}`
   },
  svgIcon () {
   return `#icon-${this.icon}`
   }
  }
}
</script>
<style scoped lang="scss">
 .ds-svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
  }
</style>

注意: 定義的每個元件都要指定 name 屬性,name 屬性的值,與目錄名稱保持一致。

3.2 封裝為外掛

上面建立了 ds-svg-icon/index.vue, 隨著開發的進行,後面還有很多元件,我們統一將其封裝為外掛,每個工程需要使用時,在 main.js 全域性引入即可。

src/components 目錄下建立 index.js

import DsSvgIcon from './ds-svg-icon'
const DSComponents = [
 DsSvgIcon
]
function plugin (Vue) {
 if (plugin.installed) {
  return
  }
 DSComponents.forEach(component => {
  Vue.component(component.name, component)
  })
}
export default plugin

後續元件開發時,都在這個檔案中匯入,並新增到陣列 DSCompoents 中。

main.js 中引入元件庫,並使用:

import DSComponent from '@/components'
...
Vue.use(DSComponent)

3.3 icons 目錄

在初始化工程的時候,已經建立了 src/icons 目錄。在該目錄下建立 svg 目錄,所有的 svg 檔案,都放在這個目錄中(src/icons/svg),現在可以將之前下載的主頁 svg 圖示拷貝到這個目錄下,將其重新命名為 icon-home.svg (說明:上面的配置約定 所有 svg 圖示都使用字首 icon-)。

svg 圖示拷貝到 src/icons/svg 目錄下後還不能立即使用,需要載入它才行。使用一個 js 檔案統一全部載入:src/icons/index.js:

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

最後在 main.js 中引入這個 js:

import '@/icons/index'

3.4 main.js

到現在為止,main.js 全部程式碼如下:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import i18n from '@/i18n'
import ElementUI from 'element-ui'
import '@/assets/scss/index.scss'
import DSComponent from '@/components'
import '@/icons/index'
Vue.use(ElementUI, {
 size: 'mini',
 i18n: (key, value) => i18n.t(key, value)
})
Vue.use(DSComponent)
Vue.config.productionTip = false
new Vue({
 router,
 store,
 i18n,
 render: h => h(App)
}).$mount('#app')

4 測試使用元件

在 App.vue 檔案中,測試剛才編寫的 ds-svg-icon 元件:

<ds-svg-icon icon="home"></ds-svg-icon>

重啟服務,在瀏覽器中能看到該圖示,則該元件 ok。

提交程式碼:

git add .
git cz
[元件開發] SVG圖示元件

合併到 master 分支:

git checkout master
git merge 02_SVGIcon

將本地分支分別全部推送到 Gitee 和 GitHub

git push --all gitee_origin
git push --all github_origin

更多內容請關注我的個人公眾號,留言可加我個人微信或交流問題