朱丽叶

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

Vue + Ts + Vite中使用svg

  1. 在项目目录的src下新建icons文件夹,svg目录下存放svg图片

  1. 编写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/")
  ],
});
  1. 如果上一步引入的时候提示这个错误
// 只需要在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");
  1. 使用
<!-- icon-class为svg图片的名称 -->
<svg-icon icon-class="peoples" class-name="card-panel-icon" />

posted on   朱丽叶  阅读(327)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示