Whidy Writes - 我的技术笔记

UnoCSS动态图标icon无法显示解决方案

发布于:

这几天遇到了一个奇怪的问题,使用UnoCSS过程中,有的icon图标能够正常显示,但是有的不能,当然最糟糕的事,我找了几天,才发现诡异之处。

问题描述

首先UnoCSS是无法通过动态的方式解析到你可能用到的icon,主要是以下2个场景可能会无法显示icon图标:

  • 后台管理系统的菜单,由后端返回菜单数据信息包含icon类名或在路由文件的meta信息中包含,由模板遍历数据来显示(我就是在这个场景下出现问题的)
  • 自己封装icon组件、通过props传递icon图标信息进行拼接的

很显然,稍微了解UnoCSS引擎的朋友,大概可以推测到,动态加载进去的图标类名无法被检测到,所以也就不能显示了,如何解决这个问题呢。

解决方案

因为我是在做菜单组件时候发现的问题,所以以菜单的场景举例说明。

方案一:图标预加载

在菜单组件写一段“没有用”的代码

<div v-if="false" i-mdi-poll i-mdi-monitor-dashboard i-mdi-ballot-recount-outline i-mdi-application-brackets-outline i-mdi-apache-kafka i-mdi-archive-search-outline i-mdi-format-text-wrapping-overflow></div>

当然你不想用 v-if 换成 hidden 也是可以的。同样的你想统一管理这所有的动态加载的icon,也可以专门写到 index.html 进行补充,因为默认状态下这些都能被UnoCSS识别到。

方案二:项目文件添加到UnoCSS扫描范围【推荐】

其实这个方案就很不错了,比如我是Vue的菜单组件中调用路由( router/menu.ts )内的每条路由记录的meta中icon,那么就给这个 menu.ts 文件顶部加一段注释

// @unocss-include export const menuRoutes = [{ name: "Index", path: "/", component: () => import("@/layout/index.vue"), isHidden: true, redirect: "/dashboard/overview", meta: { title: "首页", }, children: [{ name: "Dashboard", path: "/dashboard", component: () => import("@/views/dashboard/index.vue"), redirect: "/dashboard/overview", meta: { title: "看板", icon: "i-mdi-poll", }, // ... }] }]

这样就解决了。相同的原理,如果你想统一管理,也可以创建一个单独的文件在src目录下,比如叫做 unocss-icon.ts ,然后再在 main.ts 内引入就好了。这完全取决于你的喜好~

// unocss-icon.ts // @unocss-include const iconList = ["i-mdi-poll", "i-mdi-monitor-dashboard", "i-mdi-ballot-recount-outline", "i-mdi-application-brackets-outline", "i-mdi-apache-kafka", "i-mdi-archive-search-outline", "i-mdi-format-text-wrapping-overflow" ];
// main.js // 添加一行 import "./unocss-icon";

后记

我在Github上也做了一个简单的模板,大家可以参考一下:Vite-Element-Plus-UnoCSS

另外,为啥看起来挺简单的问题,我搞了几天。原因有几点:

  • 才上手 UnoCSS 不到一周,虽然主要功能了解,但细节仍有许多不清楚。
  • 我做菜单时,最早写的纯静态Vue组件,用的 el-menu ,没有结合路由,并且只给一级菜单加了图标,后来改造的时候,把旧的代码注释掉了,但没删除,然后通过 menu.ts 动态获取,这时,因为旧的Vue组件没有删,所以旧的图标还在,但是我给二级菜单添加的图标是之前没有的,所以造成了有的图标有,有的没有,就是旧代码注释未删除造成的假象。这也算把自己坑了~

而上面提到的解决方案之前是没有搜出来的,也没想到是因为不支持动态加载图标造成的,当我后来反复摸索发现了这个问题,才去 issue 寻找是否有人遇到类似的情况,发现确实有。

antfu 也做了一些解释,相关的issues我整理如下:

最后,最佳解决方案也是参考:UnoCSS - Scanning

avatar

Whidy

一名爱折腾的前端开发工程师,喜欢打篮球和分享 ฅʕ•̫͡•ʔฅ