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