Vue3+TS中svg图标的使用-@unocss/preset-icons

@unocss/preset-icons 是 UnoCSS 提供的图标预设,支持从 本地和在线图标库 加载图标,本文介绍本地图标库的使用

blog.csdn.net/u013737132/... 得知vite-plugin-svg-icons 插件停止维护,依赖过时,便整理替代品

准备svg文件

src/assets/icons下随意创建文件夹custom,menu

从网络上下载svg文件复制到两个文件夹下

安装依赖

bash 复制代码
pnpm add -D unocss @iconify/utils glob

配置文件

vite.config.ts

ts 复制代码
...
import vue from '@vitejs/plugin-vue'
// 导入Unocss插件
import Unocss from 'unocss/vite'
...
export default defineConfig({
	plugins: [
        vue(),
        // 注册Unocss插件
        Unocss(),
    ]
})

uno.config.ts

ts 复制代码
import { defineConfig, presetIcons, presetWind3 } from "unocss";
import { FileSystemIconLoader } from "@iconify/utils/lib/loader/node-loaders";
import { globSync } from 'glob'
import path from 'node:path'

/**
 * 获取 src/assets/icons/ 目录下的所有 svg图标文件
 * 实际只适用 icons的下一级目录,再下级目录不支持
 */
const iconsDirPattern = "./src/assets/icons/**/*.svg";
const files = globSync(iconsDirPattern, { nodir: true }) // nodir:true 不匹配目录,只匹配文件
// 读取本地 SVG 目录,获取所有 svg 图标,并按照文件夹分类
/**
 * 返回数据格式
 * {
 *   menu: [ 'i-menu:home' ],
 *   custom: [
 *     'i-custom:welcome',
 *     'i-custom:refresh',
 *     'i-custom:phone',
 *     'i-custom:logout',
 *     'i-custom:lock',
 *     'i-custom:loading',
 *     'i-custom:juejin',
 *     'i-custom:home',
 *     'i-custom:full-screen',
 *     'i-custom:exit-full',
 *     'i-custom:copyright'
 *   ]
 * }
 */
function getIcons() {
  const icons = {}
  files.forEach((filePath) => {
    const fileName = path.basename(filePath) // 获取文件名,包括后缀
    const fileNameWithoutExt = path.parse(fileName).name // 获取去除后缀的文件名
    const folderName = path.basename(path.dirname(filePath)) // 获取文件夹名
    if (!icons[folderName]) {
      icons[folderName] = []
    }
    icons[folderName].push(`i-${folderName}:${fileNameWithoutExt}`)
  })
  return icons
}
const icons = getIcons()
/**
 * 读取本地 SVG 目录,获取所有 svg 图标,并按照文件夹分类
 * 返回数据格式
 * collections {
 *   menu: [AsyncFunction (anonymous)],
 *   custom: [AsyncFunction (anonymous)]
 * }
  */
const collections = Object.fromEntries(Object.keys(icons).map(item => [
  item,
  FileSystemIconLoader(`src/assets/icons/${item}`, (svg) => {
    return svg.includes('fill="')
      ? svg
      : svg.replace(/^<svg /, '<svg fill="currentColor" ');
  })
]))

/**
 * 使用安全列表,在UnoCSS中使用动态生成的className名称
 * 提前声明那些动态生成的类名,以确保它们在最终的CSS中被包含
 * 返回数据格式
 * [
 *   'i-menu:home',
 *   'i-custom:welcome',
 *   'i-custom:refresh',
 *   'i-custom:phone',
 *   'i-custom:logout',
 *   'i-custom:lock',
 *   'i-custom:loading',
 *   'i-custom:juejin',
 *   'i-custom:home',
 *   'i-custom:full-screen',
 *   'i-custom:exit-full',
 *   'i-custom:copyright'
 * ]
 */
const generateSafeList = () => {
  return Object.keys(icons).flatMap((item) => icons[item])
};

export default defineConfig({
  presets: [
    // https://unocss.dev/presets/wind3
    presetWind3(),
    // 预设图标
    presetIcons({
      warn: true,
      prefix: ['i-'],
      // 设置全局图标默认属性
      extraProperties: {
        width: "1em",
        height: "1em",
        display: "inline-block",
      },
      // 注册本地 svg 图标集合
      collections,
    }),
  ],
  safelist: generateSafeList(), // 动态生成 `safelist`
});

使用图标

html 复制代码
<template>
  <div class="home">
    <h2>home</h2>
    测试preset-icons
    <i class="i-custom:exit-full text-#0033cc text-2xl" />
    <i class="i-menu:refresh" />
    <i class="i-custom:juejin text-red text-[50px]" />
    <i class="i-custom:lock hover:text-sky " />
  </div>
</template>

<script setup lang="ts">
</script>

<style scoped>

</style>

i-: 固定前缀
menucustom: 文件夹名
exit-fullrefresh等: svg文件名

相关推荐
HtwHUAT22 分钟前
实验四 Java图形界面与事件处理
开发语言·前端·python
利刃之灵23 分钟前
01-初识前端
前端
codingandsleeping28 分钟前
一个简易版无缝轮播图的实现思路
前端·javascript·css
天天扭码32 分钟前
一分钟解决 | 高频面试算法题——最大子数组之和
前端·算法·面试
全宝1 小时前
🌏【cesium系列】01.vue3+vite集成Cesium
前端·gis·cesium
拉不动的猪2 小时前
简单回顾下插槽透传
前端·javascript·面试
烛阴2 小时前
Fragment Shader--一行代码让屏幕瞬间变黄
前端·webgl
爱吃鱼的锅包肉2 小时前
Flutter路由模块化管理方案
前端·javascript·flutter
风清扬雨2 小时前
Vue3具名插槽用法全解——从零到一的详细指南
前端·javascript·vue.js
大熊猫今天吃什么3 小时前
【一天一坑】空数组,使用 allMatch 默认返回true
前端·数据库