1. 程式人生 > 實用技巧 >Vue3 使用 svg-sprite-loader 實現 svg 圖示按需載入

Vue3 使用 svg-sprite-loader 實現 svg 圖示按需載入

前面文章有講到 svg 圖示按需載入的優勢以及 Vue 如何使用 vue-svg-icon 實現 svg 圖示按需載入:
https://www.cnblogs.com/Leophen/p/13201907.html
今天來學習一下使用 svg-sprite-loader 在 Vue3 專案中實現圖示按需載入

1、將 email.svg 檔案匯入專案

<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path d="M4 4H20C21.1 4 22 4.9 22 6V18C22 19.1 21.1 20 20 20H4C2.9 20 2 19.1 2 18V6C2 4.9 2.9 4 4 4Z" stroke="currentColor"
    stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
  <path d="M22 6L12 13L2 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>

這裡將 svg 圖示中對應的圖示顏色值改為字串 currentColor,方便使用時控制圖示實時顏色
將圖示放在特定資料夾下,這裡以 @/assets/svg 中匯入的 svg 為例

2、安裝 svg-sprite-loader

npm i svg-sprite-loader

3、配置 vue.config.js

const path = require("path");

module.exports = {
  // 配置使用stylus全域性變數
  chainWebpack: config => {
    const svgRule = config.module.rule("svg");
    svgRule.uses.clear();
    svgRule
      .use("svg-sprite-loader")
      .loader("svg-sprite-loader")
      .options({
        symbolId: "icon-[name]"
      })
      .end();
  }
};

4、新建 SvgIcon.vue 檔案,這裡可傳入 name 屬性控制圖示型別,傳入 size 屬性控制圖示大小,傳入 color 屬性控制圖示顏色

<template>
  <svg
    class="svg-icon"
    :style="{
      width: props.size + 'px',
      height: props.size + 'px',
      color: props.color
    }"
    @mousedown="clickIcon"
  >
    <use :xlink:href="`#icon-${props.name}`" :fill="props.color" />
  </svg>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "SvgIcon",
  props: {
    name: {
      type: String,
      required: true,
      default: "email"
    },
    size: {
      type: Number,
      default: 32
    },
    color: {
      type: String,
      default: "#000"
    }
  },
  setup(props) {
    return {
      props
    };
  }
});
</script>

5、在 src 目錄下新建 plugin.ts

import SvgIcon from "@/pages/components/SvgIcon.vue";

const componentPlugin: any = {
  install: function(vue: any, options: any) {
    if (
      options &&
      options.imports &&
      Array.isArray(options.imports) &&
      options.imports.length > 0
    ) {
      // 按需引入圖示
      const { imports } = options;
      imports.forEach((name: any) => {
        require(`@/assets/svg/${name}.svg`);
      });
    } else {
      // 全量引入圖示
      const ctx = require.context("@/assets/svg", false, /\.svg$/);
      ctx.keys().forEach(path => {
        const temp = path.match(/\.\/([A-Za-z0-9\-_]+)\.svg$/);
        if (!temp) return;
        const name = temp[1];
        require(`@/assets/svg/${name}.svg`);
      });
    }
    vue.component(SvgIcon.name, SvgIcon);
  }
};
export default componentPlugin;

6、在 main.js(或 main.ts)中引入上面的 plugin 檔案

import plugin from "./plugin";

createApp(App)
  .use(plugin, {
    imports: []
  })

7、圖示元件的使用

<SvgIcon name="email" :size="24" color="#777" />