在vue專案中優雅的使用Svg

lMadman發表於2018-10-24

github demo: github地址 如果對您有用,請順手給個star...

閒聊背景

本文主要以vue-cli3搭建的專案為例,來聊一下如何在專案中更優雅的使用svg

眾所周知,vue-cli3已經推出很長一段時間了,大家可以感受一下vue-cli3帶來的零配置體驗。But,也相應帶來了一些弊端,就是如果需要修改預設的loader時,會比較麻煩。

好了,上正題,建議看此文章之前先去看一下張鑫旭大神的未來必熱:SVG Sprite技術介紹,那麼我們接下來主要使用的就是上文中提到的svguse,先上一張vue-cli3搭建的專案的目錄,可以看到根目錄下只保留了public/以及src/,可以說非常乾淨,大家可以自己建立一個。

在vue專案中優雅的使用Svg

src/components/下建立SvgIcon元件

<template>
  <svg :class="svgClass" aria-hidden="true">
    <use :xlink:href="iconName"/>
  </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>
複製程式碼

src/下建立一個icons目錄,目錄結構如下:

在vue專案中優雅的使用Svg

svg目錄主要用於存放svg檔案,來看一下index.js的內容,功能就是把元件註冊到全域性,方便使用:

import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon' // svg元件

// 註冊到全域性
Vue.component('svg-icon', SvgIcon)

const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./svg', false, /\.svg$/)
requireAll(req)
複製程式碼

當然,如果你有自己的想法或需求,可以單獨引入,無需非要註冊到全域性。

main.js中引入

在vue專案中優雅的使用Svg
這一步就沒什麼好說的了,如果需要註冊到全域性,需要在入口檔案中引入。

好了,接下來是最重要的一步:

修改預設的loader:

大家可以去vue-cli3官網去檢視具體教程,這裡我只說需要修改的loader以及具體的程式碼實現。

首先需要注意的是,通過vue-cli3構建的專案可以初始化進行很多選擇,我構建的目錄更多的是以*.config.js的形式存在的。

在根目錄下建立一個名為vue.config.js檔案,接下來的操作都和它有關,先來看一下它完整的程式碼:

const path = require('path')

function resolve (dir) {
  return path.join(__dirname, './', dir)
}

module.exports = {
  chainWebpack: config => {
    config.plugin('define').tap(args => {
      const argv = process.argv
      const icourt = argv[argv.indexOf('--icourt-mode') + 1]

      args[0]['process.env'].MODE = `"${icourt}"`

      return args
    })
    // svg rule loader
    const svgRule = config.module.rule('svg') // 找到svg-loader
    svgRule.uses.clear() // 清除已有的loader, 如果不這樣做會新增在此loader之後
    svgRule.exclude.add(/node_modules/) // 正則匹配排除node_modules目錄
    svgRule // 新增svg新的loader處理
      .test(/\.svg$/)
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]',
      })

    // 修改images loader 新增svg處理
    const imagesRule = config.module.rule('images')
    imagesRule.exclude.add(resolve('src/icons'))
    config.module
      .rule('images')
      .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
  },
  configureWebpack: {
    devServer: {
      open: true,
      // https: true,
      proxy: {
        '/user': {
          target: 'https://devadminschool.icourt.cc',
        },
        '/live': {
          target: 'https://devadminschool.icourt.cc',
        },
      },
    },
  },
}
複製程式碼

大家忽略無關緊要的程式碼,重點從svg rule loader註釋開始,其實註釋已經比較詳細了,就是獲取預設的loader並進行相關的修改,主要有svg-loaderimages-loader,從vue-cli3基礎loader中可以找到這兩個loader的預設配置。

// 預設的svg loader...
webpackConfig.module
  .rule('svg')
    .test(/\.(svg)(\?.*)?$/)
    .use('file-loader')
      .loader('file-loader')
      .options({
        name: genAssetSubPath('img')
      })
      
// 預設的images loader...
webpackConfig.module
      .rule('images')
        .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
        .use('url-loader')
          .loader('url-loader')
          .options(genUrlLoaderOptions('img'))
複製程式碼

對比我一開始的程式碼可以看出,我把預設的svg loader配置中使用的file-loader改為了svg-sprite-loader,並排除了node_modules,把預設的images-loader配置新增了svg,並排除了src/icons目錄。

如何使用?

  • 可以把設計大大給的svg 或者從iconfont官網下載開源的icon的svg格式,複製到src/icons/svg目錄下;
  • 點選svg檢視原始碼,修改fill屬性, fill="currentColor",或者fill="",如果無此屬性,就不用管,這樣做是可以讓外部控制icon的顏色,或隨父元素的color;
  • 注意svg命名和SvgIcon命名一致,看一下最終使用:
    在vue專案中優雅的使用Svg
    這裡就會使用src/icons/svg/go-back.svg檔案。

總結:

以上講的比較糙,奈何文字功底是硬傷,最後附上github demo 程式碼示例: 此專案也可以當做專案初始架構,內建了vue-router、vuex等。

本文以vue-cli3建立的專案為例,之前的專案可以直接去手動修改對應的loader即可。

github地址 如果對您有用,請順手給個star...

本文是在掘金上釋出的第一篇帖子,新人入駐,還請各位前輩多關懷...

相關文章