preface
Svg-icon is often used in our daily projects. Today we introduce SVG-Icon in the environment of Vue3+ Vite + TS
Introducing SVG plug-ins
yarn add svg-sprite-loader -D
yarn add fs -D
Copy the code
Create a file
The directory structure is as follows:
code
Index. Ts file
The code is as follows:
import { readFileSync, readdirSync } from 'fs' let idPerfix = '' const svgTitle = /<svg([^>+].*?) >/ const clearHeightWidth = /(width|height)="([^>+].*?) "/g const hasViewBox = /(viewBox="[^>+].*?" )/g const clearReturn = / (\ r) | (\ n)/g / / find SVG files function svgFind (e: 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: any, $2: any) => { 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} // Generate 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>` ) } } }Copy the code
Introduce the plug-in in viet.config.js
import { createSvg } from './src/icons/index' export default ({ mode }) => defineConfig({ plugins: [... / / SVG introduced createSvg ('. / SRC/ICONS/SVG/')]})Copy the code
Declare an SVG type file
shims-vue.d.ts
declare module "*.svg" {
const content: any;
export default content;
}
Copy the code
SvgIcon components
The code is as follows:
<template lang=""> <svg :class="svgClass" aria-hidden="true" v-on="$listeners"> <use :xlink:href="iconName" /> </svg> </template> <script> import { defineComponent, computed } from 'vue' export default defineComponent({ name: 'SvgIcon', props: { iconClass: { type: String, required: true }, className: { type: String, default: "'}}, setup(props) { const svgClass = computed(() => { if (props.className) { return 'svg-icon ' + props.className } else { return 'svg-icon' } }); const iconName = computed(() => { return `#icon-${props.iconClass}` }) return { svgClass, iconName } } }) </script> <style lang="css"> .svg-icon { width: 1em; height: 1em; fill: currentColor; vertical-align: middle; } </style>Copy the code
Inject the global component SvgIcon
Import {createApp} from 'vue' import App from '. / App. Vue 'import SvgIcon from' @ / components/SvgIcon/index. The vue '/ / SVG components Const app = createApp(app) app.ponent (' svG-icon ', SvgIcon) app.mount('#app') // Mount page to root nodeCopy the code
\
SvgIcon use
<svg-icon class-name="size-icon" icon-class="size" />
Copy the code
Results,
The icon in the upper left corner