放开双手使用svg小图标(vue3)

125 阅读1分钟
  • 平时使用图标一般是导入然后进行src引用
  • 或者封装一个组件,根据名称进行引用资源,这种方式稍微便捷一点
  • 我觉得还是有那么一点繁琐,不妨尝试一种新的使用方式

先看看最终使用效果是不是你想要的

  • Ju是一个标识固定开头,也可以自定义
  • DeviceManage存放该svg文件的文件夹,我这里配置的是src/assets/icons/svg文件夹
  • 再后面一个就是svg文件了
<el-button class="button-icon"> <Ju-DeviceManage-DeviceManage05 />导出 </el-button>
<el-button class="button-icon"> <Ju-DeviceManage-DeviceManage06 />新增 </el-button>
<el-button class="button-icon"> <Ju-DeviceManage-Upload />上传 </el-button>
<el-button class="button-icon"> <Ju-DeviceManage-DeviceManage04 />配置 </el-button>
//传参
 <Ju-DeviceManage-DeviceManage06 size="50px" />

image.png

安装

npm install vite-plugin-svg-icons --save

配置插件

  • 注意这里的"src/assets/icons中存放着你所有的svg文件夹
vite.config.ts
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
plugins:[
 createSvgIconsPlugin({
      iconDirs: [resolve(process.cwd(), "src/assets/icons")],
      symbolId: "icon-[dir]-[name]"
    }),
]

main.ts

import "virtual:svg-icons-register";

先验证效果 你可以在视图中编写

 <svg aria-hidden="true">
      <use xlink:href="#icon-文件夹名-svg文件名" />
</svg>

如果生效了就接着下一步

我们编写一个自定义的插件,直接贴代码

  • 我这个代码有待优化,自行优化吧
export const juIconPlugin = () => {
  return {
    name: "juIconPlugin",
    transform(code: string, id: string) {
      if (id.endsWith(".vue") && code.match(/<Ju([^\/>]+)\/>/g)) {
        code = code.replace(/<Ju([^\/>]+)\/>/g, (m: string) => {
          let content = (m.match(/<([^>]+)>/) as string[])[1];
          let mSize = content.match(/:size\s*=\s*["']([^"']+)["']/);
          let noMsize = content.match(/size\s*=\s*["']([^"']+)["']/);
          let size = "'18px'";
          if (mSize) {
            // 动态绑定的数据
            size = mSize[1];
          } else if (noMsize) {
            // 字符常量
            size = `'${noMsize[1]}'`;
          }

          let noMcolor = content.match(/color\s*=\s*["']([^"']+)["']/);
          let mColor = content.match(/:color\s*=\s*["']([^"']+)["']/);
          let color = "'#fff'";
          if (mColor) {
            // 动态绑定的数据
            color = mColor[1];
          } else if (noMcolor) {
            // 字符常量
            color = `'${noMcolor[1]}'`;
          }
          let noMfill = content.match(/fill\s*=\s*["']([^"']+)["']/);
          let mFill = content.match(/:fill\s*=\s*["']([^"']+)["']/);
          let fill = "'#fff'";
          if (mFill) {
            // 动态绑定的数据
            fill = mFill[1];
          } else if (noMfill) {
            // 字符常量
            fill = `'${noMfill[1]}'`;
          }
          let noMicon = content.match(/icon\s*=\s*["']([^"']+)["']/);
          let mIcon = content.match(/:icon\s*=\s*["']([^"']+)["']/);

          let iconPath = "";
          // debugger
          if (mIcon) {
            // 动态绑定的数据
            iconPath = "'#icon-'+" + mIcon[1];
          } else if (noMicon) {
            // 字符常量
            iconPath = `'#icon-${noMicon[1]}'`;
          } else iconPath = `'#icon-${(content.match(/^(\S+)/) as string[])[1].slice(3)}'`;
          return `<div class="icon-bg">
                       <svg class="svgContent" :style="{width:${size}, height: ${size}, color: ${color}, fill: ${fill}}" aria-hidden="true">
                         <use :xlink:href="${iconPath}" />
                       </svg>
                     </div>`;
        });
        // console.log(code);
        return code;
      }
    }
  };
};

引入插件

import { juIconPlugin } from "../src/plugins/svg";
  • 注意要放在vue插件的前面进行使用
plugins:[
    ....
    juIconPlugin(),
    vue(),
    .....
]
  1. 最后就可以像开始的时候进行使用啦
  2. 阅读根据目录生成svg图标对照表管理自己项目的icon