vue3+vite+ts項目中使用svg圖標|8月更文挑戰

項目結構

image.png

1. 首先引入svg插件

yarn add svg-sprite-loader -D
// 或者
npm install svg-sprite-loader -D
複製代碼

image.png

2. 建立文件

@/src裏面建立icons文件夾,裏面建立index.vue(svgicon的模板文件), index.ts(svgicon的js邏輯), svg文件夾(svg圖標存放的地址)vue

index.vue(svgicon的模板文件)

這部分須要用到fs模塊,因此須要:npm

yarn add fs
// 或者
npm install fs
複製代碼
<template>
    <svg :class="svgClass" v-bind="$attrs" :style="{ color: color }">
        <use :xlink:href="iconName"></use>
    </svg>
</template>

<script setup lang="ts">
import { computed, defineProps } from 'vue'
const props = defineProps({
    name: {
        type: String,
        required: true
    },
    color: {
        type: String,
        default: ''
    }
})
const iconName = computed(() => `#icon-${ props.name }`)
const svgClass = computed(() => {
    if(props.name) return `svg-icon icon-${ props.name }`
    return 'svg-icon'
})
</script>

<style scoped>
.svg-icon{width: 1em;height: 1em;fill:currentColor; vertical-align: middle;}
</style>
複製代碼

index.ts(svg的js邏輯文件)

這部分有問題的小夥伴能夠找我,我寫了註釋的。markdown

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) {
  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, s2, s3) => {
                                    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>`
        )
    }
  }
}
複製代碼

svg存放svg圖標

image.png

3. 在vite.config.ts裏面引用svg

import { defineConfig } from "vite"
import { createSvg } from './src/icons/index'

export default defineConfig({
    plugins: [
      vue(),
      createSvg('./src/icons/svg/')
     ]
})
複製代碼

4. 在main.ts中寫入svg-icon模板

import { createApp } from 'vue'
import App from './App.vue'
import svgIcon from './icons/index.vue'

const app = createApp(App)

app
.component('svg-icon', svgIcon)
.mount('#app')
複製代碼

醬紫,就能夠啦。(用法)

image.png

  • name是svg的名稱
  • color是svg的顏色

最後最後:

公衆號:小何成長,佛系更文,都是本身曾經踩過的坑或者是學到的東西app

有興趣的小夥伴歡迎關注我哦,我是:何小玍。 你們一塊兒進步鴨dom

相關文章
相關標籤/搜索