vue项目引入svg组件全过程

文件格式

  • 在这里插入图片描述

svg下方对应 .svg

index.vue svg-icon 组件

<template>
  <svg
    :viewBox="viewBox"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    ref="svg"
    class="svg-icon"
    :class="className"
    v-on="$listeners"
    :style="{ width: width + 'em', height: height + 'em' }"
    v-html="iconContent"
  ></svg>
</template>

<script>
export default {
  name: 'SvgIcon',
  props: {
    iconClass: {
      type: String,
      required: true
    },
    className: {
      type: String,
      default: ''
    },
    width: {
      type: Number,
      default: 1
    },
    height: {
      type: Number,
      default: 1
    }
  },
  data() {
    return {
      iconContent: null,
      viewBox: '0 0 24 24',
      test: ''
    }
  },
  watch: {
    iconClass() {
      this.loadIcon()
    }
  },
  created() {
    this.loadIcon()
  },
  methods: {
    loadIcon() {
      const fileName = `${this.iconClass}.svg`
      import(`@/icons/svg/${fileName}`).then((content) => {
        // symbol转换成svg
        const regexSymbol = /<symbol(\s[\s\S]*?)?>([\s\S]*?)<\/symbol>/g
        const svg = content.default.content.replace(regexSymbol, '<svg$1>$2</svg>')
        this.test = content
        // 获取svg内标签
        const regexSvg = /<svg([\s\S]*?)?>([\s\S]*?)<\/svg>/g
        const match = regexSvg.exec(svg)
        this.iconContent = match[2]

        // 匹配svg属性
        const regexAttr = /<svg([\s\S]*?)?>/
        const matchAttr = regexAttr.exec(svg)[1].trim()
        const viewBoxReg = /viewBox="([^"]+)"/
        const viewBoxValue = viewBoxReg.exec(matchAttr)[1]
        this.viewBox = viewBoxValue
      }).catch((err)=>{
        console.log(err)
      })
    }
  }
}
</script>

<style scoped>
.svg-icon {
  /* width: 2em;
  height: 2em; */
  vertical-align: -0.15em;
  fill: currentColor !important;
  overflow: hidden;
}
</style>

index.js 注册组件

import Vue from 'vue'
// import SvgIcon from '@/components/SvgIcon' // svg组件
import SvgIcon from './index.vue' // svg组件

// register globally
Vue.component('SvgIcon', SvgIcon)

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

主要是这段

 config.module.rule("svg").exclude.add(resolve("src/icons")).end();
    config.module
      .rule("icons")
      .test(/\.svg$/)
      .include.add(resolve("src/icons"))
      .end()
      .use("svg-sprite-loader")
      .loader("svg-sprite-loader")
      .options({
        symbolId: "icon-[name]",
      })
      .end();

安装npm i svg-sprite-loader

"svg-sprite-loader": "^6.0.11",

补充 可以不看

  • vue.config.js 主要使用带svg的那一段 这是webapck5 的配置
const { defineConfig } = require("@vue/cli-service");
const speedMeasureWebpackPlugin = require("speed-measure-webpack-plugin"); // 编译速度分析
const smp = new speedMeasureWebpackPlugin();
const path = require("path");
const isProd = process.env.NODE_ENV === "production";
let plugins = [];



module.exports = defineConfig({
  productionSourceMap: false,
  transpileDependencies: true,
  lintOnSave: false,
  devServer: {
    port: 8080,
    open: true,
    hot: true,
    allowedHosts: 'all',
    compress: true, // 是否启动压缩Gzip
    client: {
      overlay: {
        errors: true,
        warnings: false,
        runtimeErrors: false
      }
    },
   
    }
  },
  configureWebpack: smp.wrap({
    devtool: isProd ? false : "eval", // source-map eval-cheap-module-source-map
    cache: {
      type: "filesystem",
      allowCollectingMemory: true,
      buildDependencies: {
        config: [__filename],
      },
    },
    plugins: plugins,
    optimization: {
      minimize: isProd,
      splitChunks: {
        chunks: "all",
        cacheGroups: {
          common: {
            name: "chunk-common",
            chunks: "initial",
            minChunks: 2,
            maxInitialRequests: 5,
            minSize: 0,
            priority: 1,
            reuseExistingChunk: true,
            enforce: true,
          },
          vendors: {
            name: "chunk-vendors",
            test: /[\\/]node_modules[\\/]/,
            chunks: "initial",
            priority: 2,
            reuseExistingChunk: true,
            enforce: true,
          },
          elementUI: {
            name: "chunk-elementui",
            test: /[\\/]node_modules[\\/]element-ui[\\/]/,
            chunks: "all",
            priority: 3,
            reuseExistingChunk: true,
            enforce: true,
          },
          vuedraggable: {
            name: "chunk-vuedraggable",
            test: /[\\/]node_modules[\\/]vuedraggable[\\/]/,
            chunks: "all",
            priority: 8,
            reuseExistingChunk: true,
            enforce: true,
          },
          zrender: {
            name: "chunk-zrender",
            test: /[\\/]node_modules[\\/]zrender[\\/]/,
            chunks: "all",
            priority: 10,
            reuseExistingChunk: true,
            enforce: true,
          },
        },
      },
    },
    module: {
      rules: [],
    },
  }),
  chainWebpack(config) {
    if (!isProd) {
      config.optimization.minimizers.delete("terser");
      config.optimization.minimizers.delete("css");
      config.module
        .rule("js")
        .test(/\.jsx$/)
        .exclude.add(/node_modules/)
        .end();
      config.module
        .rule("jsEsbuild")
        .test(/\.js$/)
        .exclude.add(/node_modules/)
        .end()
        .use("esbuild")
        .loader("esbuild-loader")
        .options({
          loader: "js",
          target: "es2015",
        })
        .end();
    }

    config.module.rule("svg").exclude.add(resolve("src/icons")).end();
    config.module
      .rule("icons")
      .test(/\.svg$/)
      .include.add(resolve("src/icons"))
      .end()
      .use("svg-sprite-loader")
      .loader("svg-sprite-loader")
      .options({
        symbolId: "icon-[name]",
      })
      .end();
    config.plugin("html").tap((args) => {
      const date = new Date().toLocaleString();
      args[0].createDate = date;
      return args;
    });
  },
});

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值