프로젝트에서 vue-element-admin을 활용할 때, 학습 방법으로 직접 구성 요소를 만들어보는 방식을 선호합니다. 이러한 접근은 느릴 수 있지만 세부 사항까지 깊이 이해하는 데 도움이 됩니다. 이번 문서에서는 사용자 정의 SVG 아이콘 컴포넌트를 만드는 과정과 주요 단계를 기록하겠습니다.
먼저 svg-sprite-loader를 설치합니다.
yarn add svg-sprite-loader
다음으로, 전역적으로 사용할 수 있는 SVG 아이콘 컴포넌트를 설정합니다. components/SvgIcon/index.vue 파일을 생성하세요.
<template>
<svg :class="iconClass" aria-hidden="true">
<use :xlink:href="symbolId" />
</svg>
</template>
<script>
export default {
name: "CustomSvgIcon",
props: {
icon: {
type: String,
required: true,
},
customClass: {
type: String,
default: "",
},
},
computed: {
symbolId() {
return `#icon-${this.icon}`;
},
iconClass() {
if (this.customClass) {
return `svg-icon ${this.customClass}`;
}
return "svg-icon";
},
},
};
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
다음으로, src/icons 디렉토리를 생성하고 그 안에 index.js와 svg 디렉토리를 추가합니다. SVG 파일들은 svg 디렉토리에 배치됩니다.
index.js 파일의 내용은 다음과 같습니다:
import Vue from "vue";
import SvgIcon from "@/components/SvgIcon";
// 전역 컴포넌트 등록
Vue.component("custom-svg-icon", SvgIcon);
const requireAll = (context) => context.keys().map(context);
const req = require.context("./svg", false, /\.svg$/);
requireAll(req);
SVG 로더를 구성하려면 vue.config.js에서 chainWebpack 메서드를 사용하여 설정합니다.
"use strict";
const path = require("path");
function resolve(dir) {
return path.join(__dirname, dir);
}
module.exports = {
publicPath: "/",
outputDir: "dist",
assetsDir: "static",
lintOnSave: process.env.NODE_ENV === "development",
productionSourceMap: false,
configureWebpack: {
name: "G-test",
resolve: {
alias: {
"@": resolve("src"),
},
},
},
chainWebpack(config) {
config.plugins.delete("preload");
config.plugins.delete("prefetch");
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.module
.rule("vue")
.use("vue-loader")
.loader("vue-loader")
.tap((options) => {
options.compilerOptions.preserveWhitespace = true;
return options;
});
config.when(process.env.NODE_ENV === "development", (config) =>
config.devtool("cheap-source-map")
);
config.when(process.env.NODE_ENV !== "development", (config) => {
config.optimization.splitChunks({
chunks: "all",
cacheGroups: {
libs: {
name: "chunk-libs",
test: /[\\/]node_modules[\\/]/,
priority: 10,
chunks: "initial",
},
elementUI: {
name: "chunk-elementUI",
priority: 20,
test: /[\\/]node_modules[\\/]_?element-ui(.*)/,
},
commons: {
name: "chunk-commons",
test: resolve("src/components"),
minChunks: 3,
priority: 5,
reuseExistingChunk: true,
},
},
});
config.optimization.runtimeChunk("single");
});
},
};
마지막으로, main.js에서 아이콘을 포함하도록 설정합니다.
import "./icons";
이제 프로젝트 어디서든 <custom-svg-icon> 컴포넌트를 사용할 수 있습니다.
<span class="svg-container">
<custom-svg-icon icon="user" />
</span>