@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-
: 固定前缀
menu
或custom
: 文件夹名
exit-full
或refresh
等: svg文件名