文件格式
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) => {const regexSymbol = /<symbol(\s[\s\S]*?)?>([\s\S]*?)<\/symbol>/gconst svg = content.default.content.replace(regexSymbol, '<svg$1>$2</svg>')this.test = contentconst regexSvg = /<svg([\s\S]*?)?>([\s\S]*?)<\/svg>/gconst match = regexSvg.exec(svg)this.iconContent = match[2]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 {vertical-align: -0.15em;fill: currentColor !important;overflow: hidden;
}
</style>
index.js 注册组件
import Vue from 'vue'
import SvgIcon from './index.vue'
Vue.component('SvgIcon', SvgIcon)
主要是这段
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, // 是否启动压缩Gzipclient: {overlay: {errors: true,warnings: false,runtimeErrors: false}},}},configureWebpack: smp.wrap({devtool: isProd ? false : "eval", // source-map eval-cheap-module-source-mapcache: {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);
}