手把手撸后台-svg
vite 篇
安装
bash
npm i vite-plugin-svg-icons -S
svgicon 封装
vue
<template>
<!-- 判断是否是外部链接 -->
<img
v-if="isExternall"
:src="props.icon"
v-bind="$attrs"
:style="{ width: size + 'px', height: size + 'px' }"
/>
<!-- 判断是否是内置图标 -->
<svg v-else v-bind="$attrs" :width="size" :height="size">
<use :xlink:href="iconName" :style="{ fill: color }"></use>
</svg>
</template>
<script setup>
const props = defineProps({
//图标名称,会根据传入的信息来判断是否为外链
icon: {
type: String,
required: true,
},
//svg图标颜色
color: {
type: String,
},
//svg图标大小
size: {
type: String,
required: true,
},
});
const isExternall = computed(() => /(https?:|mailto:tel:)/.test(props.icon));
const iconName = computed(() => `#icon-${props.icon}`);
</script>
<style scoped></style>
vite.config.js 配置
- 这里特别注意的就是路径,因为我们是把所有的 svg 文件都放在了 src/assets/icon 文件夹下,所以路径就是 src/assets/icon
js
import { fileURLToPath, URL } from "node:url";
import path from "path";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueDevTools from "vite-plugin-vue-devtools";
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite"; // 按需加载自定义组件
// 引入svg
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
AutoImport({
imports: ["vue", "vue-router"],
dts: "src/auto-import.d.ts",
}),
Components({
// 解决命名冲突
directoryAsNamespace: true,
dts: true, //
dirs: ["src/components"], // 按需加载的文件夹
// resolvers: [ // 设置UI框架自动加载
// ElementPlusResolver(), // Antd 按需加载
// AntDesignVueResolver() // ElementPlus按需加载
// ]
}),
// 配置svg 图标
createSvgIconsPlugin({
// 指定需要缓存的图标文件夹
iconDirs: [path.resolve(process.cwd(), "src/assets/icon")],
// 指定symbolId格式
symbolId: "icon-[name]",
/**
* 自定义插入位置
* @default: body-last
*/
inject: "body-last" | "body-first",
/**
* custom dom id
* @default: __svg__icons__dom__
*/
customDomId: "__svg__icons__dom__",
svgoOptions: {
plugins: [
{
// 清除svg部分属性
name: "removeAttrs",
params: { attrs: ["fill", "stroke"] },
},
],
},
}),
],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
extensions: [".js", ".json", ".ts", ".vue"],
},
});
main.js 引入
js
import "virtual:svg-icons-register";
import svgIcon from "@/components/SvgIcon/index";
const app = createApp(App);
app.component("svgIcon", svgIcon);
app.mount("#app");
使用
html
<svgIcon icon="eye" color="red" size="56" />
<svgIcon
icon="https://file.jsopy.com/svgAll/chengxuyuan.svg"
color="red"
size="56"
/>
webpack 篇幅
安装
bash
npm i --save-dev svg-sprite-loader@6.0.9 --legacy-peer-deps
修改 vue.config.js
- 特别注意的就是目录 src/icons 目录
js
const { defineConfig } = require("@vue/cli-service");
const path = require("path");
function resolve(dir) {
return path.join(__dirname, dir);
}
module.exports = defineConfig({
transpileDependencies: true,
chainWebpack(config) {
// 设置 svg-sprite-loader
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();
},
});
创建 sVgicon 组件
- 在 components 文件夹下面创建 SvgIcon 文件夹里面创建 index.vue 文件
vue
<template>
<!--展示外部图标-->
<div
v-if="isExternal"
:style="styleExternalIcon"
class="svg-external-icon"
:class="className"
></div>
<!--展示内部图标-->
<svg v-else class="svg-icon" :class="className" aria-hidden="true">
<use :xlink:href="iconName" />
</svg>
</template>
<script setup>
import { defineProps, computed } from "vue";
const props = defineProps({
// icon图标
icon: {
type: String,
required: true,
},
// 图标类名
className: {
type: String,
default: "",
},
});
/* 判断法则 */
const external = (path) => {
return /^(https?:|mailto:|tel:)/.test(path);
};
/*
当前图标是否为外部图标,
*/
const isExternal = computed(() => {
return external(props.icon);
});
/*
外部图标样式,
*/
const styleExternalIcon = computed(() => {
return {
mask: `url(${props.icon}) no-repeat 50% 50%`,
"-webkit-mask": `url(${props.icon}) no-repeat 50% 50%`,
};
});
/*
内部图标
*/
const iconName = computed(() => {
return `#icon-${props.icon}`;
});
</script>
<style lang="scss" scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: 0.1em;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover !important;
display: inline-block;
}
</style>
- 在 src 目录下面新建 icons 文件夹,在下面创立 svg 文件夹把所有的图标都放到下面,然后在 icons 文件夹下面新建 index.js 文件
js
import SvgIcon from "@/components/SvgIcon";
// https://webpack.docschina.org/guides/dependency-management/#requirecontext
// 通过 require.context() 函数来创建自己的 context
// 第一个要搜索的目录,第二个表示是否搜索子目录,第三个表示正则表达式
const svgRequire = require.context("./svg", false, /\.svg$/);
// 此时返回一个 require 的函数,可以接受一个 request 的参数,用于 require 的导入。
// 该函数提供了三个属性,可以通过 require.keys() 获取到所有的 svg 图标
// 遍历图标,把图标作为 request 传入到 require 导入函数中,完成本地 svg 图标的导入
svgRequire.keys().forEach((svgIcon) => svgRequire(svgIcon));
export default (app) => {
app.component("svg-icon", SvgIcon);
};
修改 main.js 文件
js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
// 增加的
import installIcons from "@/icons";
const app = createApp(App);
// 增加的
installIcons(app);
app.use(store).use(router).mount("#app");
使用
js
<SvgIcon icon="eye" className="svgbox"></SvgIcon>