Vue + Ts + Vite中使用svg
- 在项目目录的src下新建icons文件夹,svg目录下存放svg图片
- 编写index.ts文件
// 2.1 首先安装用到的插件
npm install svg-sprite-loader --save-dev
npm install fs
// 2.2 index.ts文件如下
import { readFileSync, readdirSync } from "fs";
let idPerfix = "";
const svgTitle = /<svg([^>+].*?)>/;
const clearHeightWidth = /(width|height)="([^>+].*?)"/g;
const hasViewBox = /(viewBox="[^>+].*?")/g;
const clearReturn = /(\r)|(\n)/g;
// 查找svg文件
function svgFind(e: any): any {
const arr = [];
const dirents = readdirSync(e, { withFileTypes: true });
for (const dirent of dirents) {
if (dirent.isDirectory()) arr.push(...svgFind(e + dirent.name + "/"));
else {
const svg = readFileSync(e + dirent.name)
.toString()
.replace(clearReturn, "")
.replace(svgTitle, ($1, $2) => {
let width = 0,
height = 0,
content = $2.replace(
clearHeightWidth,
(s1: any, s2: any, s3: any) => {
if (s2 === "width") width = s3;
else if (s2 === "height") height = s3;
return "";
}
);
if (!hasViewBox.test($2))
content += `viewBox="0 0 ${width} ${height}"`;
return `<symbol id="${idPerfix}-${dirent.name.replace(
".svg",
""
)}" ${content}>`;
})
.replace("</svg>", "</symbol>");
arr.push(svg);
}
}
return arr;
}
// 生成svg
export const createSvg = (path: any, perfix = "icon") => {
if (path === "") return;
idPerfix = perfix;
const res = svgFind(path);
return {
name: "svg-transform",
transformIndexHtml(dom: String) {
return dom.replace(
"<body>",
`<body><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position: absolute; width: 0; height: 0">${res.join(
""
)}</svg>`
);
},
};
};
3.在vite.config.ts 中添加
import { createSvg } from "./src/icons/index";
export default defineConfig({
plugins: [
vue(),
createSvg("./src/icons/svg/")
],
});
- 如果上一步引入的时候提示这个错误
// 只需要在tsconfig.node.json中配置添加
5.自定义svgIcon组件
<template>
<div v-if="isShow" :style="styleExternalIcon" class="svg-external-icon svg-icon"></div>
<!-- v-on="$listeners" -->
<svg v-else :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName" />
</svg>
</template>
<script setup lang='ts'>
import { computed, defineProps, withDefaults, } from "vue"
import { isExternal } from '@/utils/validate'
const props = withDefaults(defineProps<{
iconClass: string
className?: string
}>(), {
className: ''
})
//
const isShow = computed(() => isExternal(props.iconClass))
console.log(isShow.value);
const iconName = computed(() => `#icon-${props.iconClass}`)
const svgClass = computed(() => {
if (props.className) {
return 'svg-icon ' + props.className
} else {
return 'svg-icon'
}
})
const styleExternalIcon = computed(() => {
return {
mask: `url(${props.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${props.iconClass}) no-repeat 50% 50%`
}
})
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover !important;
display: inline-block;
}
</style>
6.在main.ts中注册即可
import svgIcon from "./components/svgIcon/svgIcon.vue";
createApp(App)
.component("svgIcon", svgIcon)
.mount("#app");
- 使用
<!-- icon-class为svg图片的名称 -->
<svg-icon icon-class="peoples" class-name="card-panel-icon" />
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了