当前位置: 首页 > article >正文

Vue3.5 企业级管理系统实战(五):图标组件

图标组件是前端开发中常用的元素,常见开发方式有三种:字体图标、SVG图标和图片图标。

字体图标:把图标当字体处理,每个图标对应字体字符。可通过设置字体属性控制显示,如 Font Awesome 库,引入 CSS 文件后即可使用。优点是易改大小、颜色且不失真,文件小加载快;缺点是只能单色,更新需重新生成字体文件。

SVG 图标:基于 XML 语法,可无损缩放、支持丰富效果。可内联 SVG 代码到 HTML,也能在前端框架封装成组件。优点是支持多色、无损缩放、可做动画交互;缺点是代码量大、旧版浏览器可能有兼容问题。

图片图标:将图标存为 PNG 等格式,用 <img> 标签或 CSS background - image 显示。优点是简单易用、兼容性好;缺点是不能无损缩放、文件大、难动态改颜色。

鉴于前文所述,本项目已完成支持图标的 UnoCSS 安装。UnoCSS 图标优势显著,灵活性高,支持按需引入,既能减小项目体积以加快加载速度,又能在运行时借助 CSS 类动态调整样式;集成便捷,以纯 CSS 实现,无额外 JavaScript 运行时负担,还能与 UnoCSS 原子化框架完美融合;视觉效果佳,基于 SVG 可无损缩放,且能呈现多色图标满足复杂设计;自定义能力强,允许用户添加自定义 SVG 图标并通过自定义 CSS 类打造独特风格。综合这些优点,我们决定采用 UnoCSS 开展图标配置工作。

采用 UnoCSS 配置图标,同时使用 Iconify 作为图标数据源。

1 安装插件

通过 pnpm 安装插件 @unocss/preset-icons 和 @iconify-json/ant-design 

pnpm i @unocss/preset-icons @iconify-json/ant-design -D

@unocss/preset-icons 是 UnoCSS 的预设,用于在 UnoCSS 框架里集成图标支持。它支持多种图标源,借助简单的 CSS 类名,如 i-{图标集前缀}-{图标名称},就能快速在项目中使用图标。还可自定义配置图标样式,如调整大小、颜色等。

@iconify-json/ant-design 是包含 Ant Design 图标集的 JSON 数据包。Ant Design 图标丰富美观,该包将图标以 JSON 格式管理。它能与 Iconify 无缝集成,方便在不同项目和框架中使用 Ant Design 图标。

在 uno.config.ts 中修改 uno 配置

//uno.config.ts
import { defineConfig } from "unocss";
import presetAttributify from "@unocss/preset-attributify";
import presetUno from "@unocss/preset-uno";
import transformDirective from "@unocss/transformer-directives";
// unocss图标预设会查找 依赖的图标库
// ant-design
import presetIcons from "@unocss/preset-icons";
export default defineConfig({
  presets: [presetAttributify(), presetUno(), presetIcons()],
  transformers: [transformDirective()], // apply
});

2 页面图标使用

去 Iconify 官网上,搜索我们安装的 ant-design 图标库,点击想要使用的图标,复制 Icon name (如 ant-design:account-book-filled)备用。

在页面中通过 i-{ Icon name} 即可使用,如下:

页面效果如下

3 图标原子类快捷方式

在使用 UnoCSS 集成图标时,若要为图标添加可复用样式,配置 UnoCSS 的 shortcuts 功能会是极为有效的解决方案。shortcuts 具备强大的自定义能力,支持用户定义原子化 CSS 类名的组合。用户只需创建一个涵盖图标样式相关原子类的快捷方式,后续在项目中就能直接调用该快捷类名,无需反复编写多个原子类,显著提升开发效率,让代码更加简洁易读。

比如,原本的写法如下,多个图标就要重复写多个同样的样式名称:

在 uno.config.ts 中配置  shortcuts: [["icon", "inline-block w-1em h-1em align-middle text-current"]],其中,icon 就是我们自定义的快捷类名,它将可复用的图标样式原子类组合到一起。

//uno.config.ts
import { defineConfig } from "unocss";
import presetAttributify from "@unocss/preset-attributify";
import presetUno from "@unocss/preset-uno";
import transformDirective from "@unocss/transformer-directives";
// unocss图标预设会查找 依赖的图标库
// ant-design
import presetIcons from "@unocss/preset-icons";
export default defineConfig({
  presets: [presetAttributify(), presetUno(), presetIcons()],
  transformers: [transformDirective()], // apply
  shortcuts: [["icon", "inline-block w-1em h-1em align-middle text-current"]]
});

配置好后,可以在页面中使用快捷类名来定义统一的图标样式。

页面效果如下,F12可以看到样式已经添加上。

4 图标组件 svg-icon 封装

上文中的使用方式,如果我们想要使用其他图标资源,就需要手动下载相应的图标资源库,这样不仅容易造成文件冗余,使用过程繁琐,而且加载的图标还可能出现锯齿等显示问题。为解决这些痛点,实现以组件形式在 Vue 项目中渲染图标,可安装插件 @iconify/vue。@iconify/vue 是用于 Vue 项目集成 Iconify 图标功能的库,优势显著:

  1. 资源丰富调用统一:整合超 150 个图标集,像 Material Design Icons、Font Awesome、Ant Design Icons 等,超 20 万个图标,满足多样需求。且无论用哪个图标集,都能用统一语法引用,如 <Icon icon="mdi:home" />,降低学习成本、提升开发效率。

  2. 渲染质量高:基于 SVG 渲染图标,相比传统图标字体,在任何尺寸下都清晰锐利,无模糊锯齿,视觉效果好。同时,因 SVG 支持多色,能轻松实现多色图标显示,满足复杂设计需求。

  3. 资源管理高效:支持按需加载,组件会根据实际使用情况,自动从 Iconify API 加载所需图标数据,无需打包所有图标,减小项目体积、加快页面加载。图标库更新时,也无需手动更新文件,组件自动获取最新数据。

  4. 框架集成性佳:专为 Vue 设计,与 Vue 生态无缝融合,可方便地在组件中使用。还能结合 Vue 响应式特性,实现动态图标切换。此外,支持与 Vue 样式绑定机制结合,动态改变图标大小、颜色、旋转等样式。

  5. 社区文档完善:Iconify 有活跃社区,开发者可分享经验、交流问题。同时提供详细文档与示例代码,初学者也能快速上手,降低使用门槛。

通过 pnpm 安装插件 @iconify/vue

pnpm i @iconify/vue

 

在 src 下新建文件夹 utils,新建文件 validate.ts,新增判断是否外部链接的方法

//validate.ts

//是否外部链接
export const isExternal = (path: string): boolean => {
  return /https?/.test(path);
};

在 src/components 文件夹下新建 SvgIcon 文件夹,新建 index.vue 文件,封装图标组件如下:

//SvgIcon/index.vue
<template>
  <IconifyIcon
    :class="svgClass"
    :icon="iconName"
    v-if="!isExt"
    v-bind="$attrs"
  ></IconifyIcon>
  <div
    v-else
    :style="styleExternalIcon"
    :class="svgClass"
    bg-current
    v-bind="$attrs"
  ></div>
</template>
<script setup lang="ts">
import { isExternal } from "@/utils/validate";
import { Icon as IconifyIcon } from "@iconify/vue";

const { iconName, customClass } = defineProps({
  iconName: {
    type: String,
    default: ""
  },
  customClass: {
    type: String,
    default: ""
  }
});

const isExt = computed(() => isExternal(iconName));
// class="customClass + icon"
// 组合成的类名
const svgClass = computed(() => (customClass ? `icon ${customClass}` : "icon"));

// 通过mask 渲染svg 图标 兼容性不好,可以通过请求svg的方式来渲染
const styleExternalIcon = computed(() => ({
  mask: `url(${iconName}) no-repeat 50% 50%`,
  "-webkit-mask": `url(${iconName}) no-repeat 50% 50%`,
  "mask-size": "cover"
}));
</script>

<!-- 在实现图标的时候 尽量采用svg, 不要采用font图标,font图标放大时会出现锯齿等问题 -->

该图标组件主要功能是根据传入的图标名称动态渲染图标,支持使用 @iconify/vue 库渲染图标以及外部 svg 图标。该组件接收 iconName 和 customClass 两个属性。iconName 表示要渲染的图标名称,customClass 是可选的自定义类名。组件会根据 iconName 是否为外部链接来决定渲染方式:

  • 若 iconName 不是外部链接,使用 @iconify/vue 库中的 IconifyIcon 组件来渲染图标,并应用 svgClass 作为样式类,同时将其他未定义的属性透传。

  • 若 iconName 是外部链接,渲染一个 div 元素,通过 mask 和 -webkit-mask CSS 属性使用外部 SVG 图标,同样应用 svgClass 作为样式类,并透传其他属性。

5 svg-icon 组件使用

在页面中使用 svg-icon 组件,第一个组件使用本地图标,第二个组件使用外部 SVG 图标。

//Dashboard/index.vue
<template>
  <div i-ant-design:account-book-filled icon></div>
  <div i-ant-design:aim-outlined icon></div>
  <svg-icon
    icon-name="material-symbols-light:18-up-rating-outline-rounded"
  ></svg-icon>
  <svg-icon
    icon-name="https://zishui.oss-cn-beijing.aliyuncs.com/BugFilled.svg"
    :custom-class="val"
    @click="handle"
  ></svg-icon>
</template>

<script lang="ts" setup>
const { proxy } = getCurrentInstance()!;

const handle = () => {
  proxy?.$message("This is a message.");
};

const val = ref("text-blue");

setTimeout(() => {
  val.value = "text-red";
}, 1000);
</script>

页面效果如下,控制台可以看到渲染方式从之前的base64变成了svg形式。与 Base64 图标相比,svg 图标优势突出。视觉上,svg 基于矢量可无损缩放,在各分辨率设备都清晰,还能实现多色与复杂图形;Base64 缩放易失真。文件性能方面,svg 文件小,可被浏览器有效缓存,减少加载时间;Base64 编码后体积增加,缓存不便。开发维护上,svg 是文本格式,可直接编辑,便于复用和扩展;Base64 修改繁琐。另外,svg 中的文本利于 SEO,Base64 则无此优势。

以上,图标组件封装完毕。

下一篇将简单探讨Vue3中defineProps用法,敬请期待~


    http://www.kler.cn/a/537181.html

    相关文章:

  1. 蓝桥杯Java之输入输出练习题
  2. python编程-内置函数reversed(),repr(),chr()详解
  3. JVM执行流程与架构(对应不同版本JDK)
  4. 7个国内能打开的AI绘画网站!新手福音!
  5. 【GitLab CI/CD 实践】从 0 到 1 搭建高效自动化部署流程
  6. 使用Python创建、读取和修改Word文档
  7. 远程 IO 模块:汽车零部件产线的高效生产引擎
  8. AI智算-k8s部署DeepSeek Janus-Pro-7B 多模态大模型
  9. 探索从传统检索增强生成(RAG)到缓存增强生成(CAG)的转变
  10. selenium使用
  11. Stable Diffusion的入门介绍和使用教程
  12. 如何在Swift中实现基本的UI设计?
  13. AI眼镜-推理成本降低将加速端侧硬件智能化-AI 眼镜、AI玩具、手机AI化
  14. Mixture of Experts(专家混合模型)深入解析:突破传统神经网络的计算瓶颈
  15. unity学习32:角色相关1,基础移动控制
  16. 课程知识图谱生成系统设计与实现
  17. 【Android】版本和API对应关系表
  18. BUU27 [SUCTF 2019]CheckIn1
  19. Android开发经验谈:2021年Android网络编程总结篇,经典好文_android网络编程心得
  20. 【redis】redis集群时的槽Slot是什么?
  21. 深度学习:解码智能的“数字炼金术”
  22. Java面试题及答案整理( 2022最新版,持续更新)
  23. 链式前向星复习图论
  24. 【GitHub】相关工具下载及使用
  25. 高阶C语言|和结构体与位段的邂逅之旅
  26. 109,【1】攻防世界 web 题目名称-文件包含