【Nova UI】十、打造组件库第一个组件-图标组件(下):从.svg 到 SVG Vue 组件的高效蜕变✨

序言

在组件库开发的精彩旅程中🚀,我们已经成功打造并完善了图标组件体系,赋予其强大的功能和丰富的表现力🎉。然而,随着业务版图的不断扩张🌐,手动逐个编写 SVG Vue 组件的传统方式,逐渐暴露出效率低下的短板。这种重复性的工作不仅耗费大量宝贵的时间⏳与精力💪,还容易在机械的操作中引入人为错误🚫。今天,让我们一同踏上探索自动化生成的奇妙之路🧭,聚焦于如何借助神奇的代码力量,通过.svg 文件自动生成 SVG Vue 组件,开启简化操作的崭新时代🌟。这一转变将如同为组件库开发装上了涡轮增压引擎,推动开发效率实现质的飞跃,让我们的开发工作更加高效、流畅 。

思路

为深入理解自动生成的实现逻辑,我们从阿里图库下载了一个典型的.svg 文件。其内部结构如下:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#2c2c2c" d="M474 152m8 0l60 0q8 0 8 8l0 704q0 8-8 8l-60 0q-8 0-8-8l0-704q0-8 8-8Z"  /><path fill="#2c2c2c" d="M168 474m8 0l672 0q8 0 8 8l0 60q0 8-8 8l-672 0q-8 0-8-8l0-60q0-8 8-8Z"  />
</svg>

剖析这个文件可知,我们所需的关键信息集中在<svg>节点及其子节点内容。为达成从.svg 文件到 SVG Vue 组件的转换,首要任务是读取该文件📄,精准提取所需数据📊,巧妙移除<svg>节点的非必要属性,最终依据处理后的数据生成对应的 Vue 文件📝。

读取 .svg 文件

const readFile = () => {const result = {}const files = fs.readdirSync(assetsRoot)files.forEach(file => {const path = `${assetsRoot}/${file}`let content = fs.readFileSync(path, 'utf8')content = format(content)const name = file.replace('.svg', '')result[name] = content})return result
}

此函数犹在指定目录assetsRoot中,读取所有.svg 文件。对每个文件,它打开并读取内容,进行格式化处理,然后提取文件名(去除.svg 后缀)作为键,将处理后的内容作为值,存入结果对象。

提取 svg 标签

function extractSvg(content) {const startIndex = content.indexOf('<svg')const endIndex = content.lastIndexOf('</svg>') + '</svg>'.lengthreturn content.slice(startIndex, endIndex)
}

该函数在整个文件内容中定位<svg>标签的起始和结束位置,然后将这部分内容完整地裁剪出来。这一步确保我们只保留了与 SVG 图形直接相关的部分,为后续的处理提供了纯净的数据基础 。

移除svg标签非必要属性

function removeAttribute(content) {const removeAttrs = ['id', 'pid', 'class', 'width', 'height', 'version', 'fill']removeAttrs.forEach(attr => {const reg = new RegExp(` ${attr}="[^"]*"`, "g")content = content.replace(reg, '')})content = content.replace('<svg', '<svg fill="currentColor"')return content
}

这部分代码专门清理<svg>标签中那些我们不需要的属性。通过正则表达式,它逐个匹配并移除诸如idpidclass等非必要属性。同时,为了确保图标颜色能根据上下文灵活变化,它将<svg>标签的fill属性替换为fill="currentColor"。经过这一番清理和设置,<svg>标签变得简洁且符合我们的需求 。

将 提取的 svg 内容 转为 vue 内容

function toComponentContent(name, content) {const result = `
<template>${content}
</template><script setup>defineOptions({name: 'N${name}Svg',})
</script>
`return result
}

这个函数将提取并处理好的 SVG 内容,巧妙地包装成 Vue 组件的形式。它创建了一个包含<template><script setup>的 Vue 组件模板,将 SVG 内容放入<template>中,并在<script setup>中定义了组件的名称。经过这一步,原本的 SVG 数据摇身一变,成为了可以在 Vue 项目中直接使用的组件 。

驼峰转换

function toGreatHump(value) {return value.split('-').map(item => item.replace(item.charAt(0), item.charAt(0).toUpperCase())).join('')
}

该函数对字符串进行驼峰命名法的转换。它将以-分隔的字符串,转换为每个单词首字母大写的驼峰形式。例如,icon-close会被转换为IconClose。这种转换使得组件名称在符合 Vue 命名规范的同时,也更具可读性和一致性 。

写入vue文件

function writeComponentFile(key, content) {const greatHumpName = toGreatHump(key)const data = toComponentContent(greatHumpName, content)const path = `${componentsRoot}/${key}.vue`fs.writeFile(path, data, error => error && console.error(error))
}

这部分代码将转换好的 Vue 组件内容写入到指定路径的.vue 文件中。它先将文件名转换为驼峰形式,然后结合之前生成的 Vue 组件内容,将数据写入到componentsRoot目录下对应的.vue 文件。如果在写入过程中出现错误,它会在控制台输出错误信息,方便我们及时排查和解决问题 。

转成import、export语句

function toImport(keys) {return keys.map(key => `import ${toGreatHump(key)} from './components/${key}.vue'`).join('\n')
}
function toExport(keys) {return `export {${keys.map(key => toGreatHump(key)).join(',\n  ')}
}`
}

这两个函数负责生成导入和导出语句。toImport函数遍历所有的组件文件名,生成对应的import语句,这些语句将每个组件从其对应的.vue 文件中引入。toExport函数则将所有组件名以合适的格式组合成export语句,方便在其他地方统一引入这些组件。通过这两个函数,我们构建了一个清晰的组件导入导出体系,使得组件在项目中的使用更加便捷 。

转为 TS type语句

function toType(keys) {return `export const svgs = [\n${keys.map(key => `  '${toGreatHump(key)}'`).join(',\n')},\n] as const`
}

此函数将所有组件名整理成一个类型声明语句。这个语句定义了一个包含所有组件名的常量数组svgs,并且使用as const确保其类型为只读常量数组。在 TypeScript 项目中,这个声明有助于在使用这些组件时进行类型检查,提高代码的安全性和稳定性 。

写入主入口文件

function writeMainFile(keys) {const importData = toImport(keys)const exportData = toExport(keys)const typeData = toType(keys)const data = `${importData}\n\n${exportData}\n\n${typeData}\n`const path = `${mainRoot}/index.ts`fs.writeFile(path, data, error => error && console.error(error))
}

这个函数是整个自动化流程的 “收尾大师”🎨,它将前面生成的导入语句、导出语句和类型声明语句整合在一起,写入到主入口文件index.ts中。这个文件就像是组件库的大门,所有外部对组件库的访问都通过这个文件进行。通过将这些关键信息写入其中,我们完成了组件库的整体搭建,使得所有组件能够有序地被引入和使用 。

文件写入

const writeFile = json => {for (const key in json) {if (Object.prototype.hasOwnProperty.call(json, key)) {writeComponentFile(key, json[key])}}const keys = Object.keys(json)writeMainFile(keys)
}

这个函数是整个自动化流程的 “指挥官”👨‍✈️,它统筹协调各个部分的工作。它遍历包含所有 SVG 文件内容的对象,对每个文件内容调用writeComponentFile函数,将其写入对应的.vue 文件。然后,收集所有的文件名,调用writeMainFile函数,将相关的导入、导出和类型声明语句写入主入口文件。通过这个函数的调度,整个自动化生成过程得以有条不紊地完成 。

运行

function run() {const json = readFile()writeFile(json)
}run()

只要运行这个run方法,就会在packages/svgs/components下生成对应的 Vue 文件,在packages/svgs/生成index.ts主入口文件。

你以为到这里就够了吗?还不行!每次运行的时候都要切换到packages/svgs目录下,这显然不是很便捷。所以,我们可以在根目录下的package.json文件中scripts属性下增加一行 "svg:build": "pnpm -C packages/svgs run init" 。这样,每次只要在packages\svgs\assets目录下放上.svg 文件,并在命令行运行npm run svg:build,就会自动生成所需的组件和主入口文件。是不是超级方便呢?这一优化让我们的开发流程更加流畅,大大提高了工作效率,为组件库的持续发展和完善提供了有力支持 。

🦀🦀感谢看官看到这里,如果觉得文章不错的话🙌,点个关注不迷路⭐。
诚邀您加入我的微信技术交流群🎉,群里都是志同道合的开发者👨‍💻,大家能一起交流分享摸鱼🐟。期待与您在群里相见🚀,咱们携手在开发路上共同进步✨ !
👉点我

感谢各位大侠一路相伴,实在感激! 不瞒您说,在下还有几个开源项目 📦,它们就像精心培育的幼苗 🌱,急需您的浇灌。要是您瞧着还不错,麻烦动动手指,给它们点亮几颗 Star ⭐,您的支持就是它们成长的最大动力,在此谢过各位大侠啦!

  • Nova UI组件库:https://github.com/gmingchen/nova-ui
  • 基于 Vue3 + Element-plus 管理后台基础功能框架
  • 预览:https://admin.gumingchen.icu
    • Github:https://github.com/gmingchen/agile-admin
    • Gitee:https://gitee.com/shychen/agile-admin
    • 基础版后端:https://github.com/gmingchen/java-spring-boot-admin
    • 文档:http://admin.gumingchen.icu/doc/
  • 基于 Vue3 + Element-plus + websocket 即时聊天系统
    • 预览:https://chatterbox.gumingchen.icu/
    • Github:https://github.com/gmingchen/chatterbox
    • Gitee:https://gitee.com/shychen/chatterbox
  • 基于 node 开发的后端服务:https://github.com/gmingchen/node-server

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/77150.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Golang | 倒排索引

文章目录 倒排索引的设计倒排索引v0版实现 倒排索引的设计 通用搜索引擎 v.s. 垂直搜索引擎&#xff1a; 通用搜索引擎&#xff1a;什么都可以搜索&#xff0c;更加智能化垂直搜索引擎&#xff1a;只能搜自家数据库里面的内容&#xff0c;一般都带着搜索条件&#xff0c;搜索一…

Windows 10 上运行 Ollama 时遇到 llama runner process has terminated: exit status 2

在 Windows 10 上运行 Ollama 时遇到 llama runner process has terminated: exit status 2 错误&#xff0c;可能是由多种原因引起的。以下是逐步解决方案&#xff1a; 1. 检查 Ollama 服务状态 按 Win R 输入 services.msc&#xff0c;找到 Ollama 服务&#xff0c;确保其状…

PCI 总线学习笔记(五)

PCI 总线学习系列&#xff0c;参考自 技术大牛博客&#xff1a; PCIe 扫盲系列博文连载目录篇 书籍&#xff1a;王齐老师的《PCI Express 体系结构导读》 下面的文章中加入了自己的一些理解和实际使用中遇到的一些场景&#xff0c;供日后查询和回忆使用 PCI 总线定义了两类配置…

Spring Cloud Alibaba VS Spring Cloud

​​Spring Cloud Alibaba 与 Spring Cloud 组件对比​ ​​服务发现与注册中心​ 功能​​​Spring Cloud​​​Spring Cloud Alibaba​对比说明​​核心组件​EurekaNacosNacos 支持动态配置管理、健康检查更灵活&#xff0c;且提供 DNS 服务发现能力。​​​​健康检查​​…

Java—— 常见API介绍 第五期

JDK8以后新增的时间相关类 Date类ZoneId&#xff1a;时区Instant&#xff1a;时间戳ZoneDateTime&#xff1a;带时区的时间 日期格式化类 SimpleDateFormat DateTimeFormatter&#xff1a;用于时间的格式化和解析 日历类 Calendar LocalDate&#xff1a;年、月、日LocalTime…

Java与Kotlin在Android开发中的全面对比分析

趋势很重要 语言发展背景与现状 Android操作系统自2008年正式发布以来&#xff0c;Java长期作为其主要的开发语言。这种选择源于Java语言的跨平台特性、成熟的生态系统以及广泛开发者基础。然而&#xff0c;随着移动开发需求的快速演变&#xff0c;Java在Android开发中逐渐暴…

第一部分:git基本操作

目录 1、git初识 1.1、存在的问题 1.2、版本控制器 1.3、git安装 1.3.1、CentOS平台 1.3.2、ubuntu平台 2、git基本操作 2.1、创建仓库 2.2、配置git 3、工作区、暂存区、版本库 4、基本操作 4.1、场景一 4.2、场景二 4.3、修改文件 5、版本回退 6、撤销修改 …

正则表达式与python使用

一、Python正则表达式基础 1. 导入模块 Python通过 re 模块实现正则表达式功能&#xff0c;需先导入模块&#xff1a; import re2. 核心语法 普通字符&#xff1a;直接匹配字面值&#xff08;如 a 匹配字符 a&#xff09;。元字符&#xff1a; \d&#xff1a;匹配数字&…

从FP32到BF16,再到混合精度的全景解析

笔者做过目标检测模型、超分模型以及扩散生成模型。其中最常使用的是单精度FP32、半精度FP16、BF16。 双精度"FP64"就不说了&#xff0c;不太会用到。 #1. 单精度、半精度和混合精度 单精度&#xff08;FP32&#xff09;、半精度&#xff08;FP16&#xff09;和混合…

Hot100方法及易错点总结2

本文旨在记录做hot100时遇到的问题及易错点 五、234.回文链表141.环形链表 六、142. 环形链表II21.合并两个有序链表2.两数相加19.删除链表的倒数第n个节点 七、24.两两交换链表中的节点25.K个一组翻转链表(坑点很多&#xff0c;必须多做几遍)138.随机链表的复制148.排序链表 N…

不在同一个局域网的远程桌面连接怎么设置?本地内网计算机让其他网络远程访问6种常用方法

远程桌面是一种重要的技术&#xff0c;它允许用户通过网络远程访问和控制另一台计算机的桌面界面。但是&#xff0c;当被控制端和控制端不在同一个局域网内时&#xff0c;就需要进行一些额外的配置。本文将详细介绍在不同局域网下设置远程桌面的步骤&#xff0c;以帮助读者顺利…

天机学堂day10作业,完善兑换优惠券功能

UserCouponServiceImpl /*** 兑换码兑换优惠券* param code*/TransactionalOverridepublic void exchangeCoupon(String code) {//1、校验code是否为空if (StringUtils.isBlank(code)) {throw new BadRequestException("非法参数&#xff01;");}//2、解析兑换码&…

JAVA工程师面试题(七)

1、递归实现1,1,2,3,5,8,….第30个数是多少&#xff1f; public static int Foo(int i) { if (i < 0) return 0; else if(i > 0 && i < 2) return 1; else return Foo(i -1) Foo(i - 2); }…

Qt基础009(HTTP编程和QJSON)

文章目录 软件开发网络架构BS架构/CS架构 HTTP基本概念QT的HTTP编程JSON数据概述QT生成JSON数据QT解析JSON数据 软件开发网络架构 BS架构/CS架构 ​ 在计算机网络和软件开发中&#xff0c;CS架构&#xff08;Client-Server Architecture&#xff0c;客户端-服务器架构&#x…

高精度电流检测革命:同轴分流器的创新应用与技术演进

一、精密测量原理与结构创新 基于电磁场分布重构技术的新型同轴分流器&#xff0c;突破了传统电流测量的物理限制。该器件采用三维环形电阻矩阵结构&#xff0c;通过多层级导电环的精密排列&#xff0c;实现了电流路径的涡流自补偿。区别于常规分流器的平板式设计&#xff0c;其…

【使用层次序列构建二叉树(数据结构C)】

使用层次序列构建二叉树&#xff08;C语言实现&#xff09; 在数据结构学习过程中&#xff0c;二叉树的构建方式通常有递归建树&#xff08;前序/中序&#xff09;和层次建树&#xff08;广度优先&#xff09;两种。本文将介绍一种基于辅助队列实现的层次建树方法&#xff0c;并…

设置Rocky Linux盒盖不休眠的3个简单步骤

在 Rocky linux&#xff08;和其他基于 RHEL 的发行版&#xff09;中&#xff0c;当你关闭笔记本电脑的盖子时&#xff0c;默认行为通常是使系统休眠。如果你想更改这一行为&#xff0c;例如&#xff0c;使系统在关闭盖子时只是锁定&#xff0c;你可以按照以下步骤操作&#xf…

WPF的发展历程

文章目录 WPF的发展历程引言起源与背景&#xff08;2001-2006&#xff09;从Avalon到WPF设计目标与创新理念 WPF核心技术特点与架构基础架构与渲染模型关键技术特点MVVM架构模式 WPF在现代Windows开发中的地位与前景当前市场定位与其他微软UI技术的关系未来发展前景 社区贡献与…

【器件专题1——IGBT第1讲】IGBT:电力电子领域的 “万能开关”,如何撑起新能源时代?

一、IGBT 是什么&#xff1f;重新认识这个 “低调的电力心脏” 你可能没听过 IGBT&#xff0c;但一定用过它驱动的设备&#xff1a;家里的变频空调、路上的电动汽车、屋顶的光伏逆变器&#xff0c;甚至高铁和电网的核心部件里&#xff0c;都藏着这个 “电力电子开关的瑞士军刀”…

新闻速递丨Altair 与 Databricks 达成合作,加速数据驱动型创新

NEWS Altair 近日宣布与数据和人工智能公司 Databricks 达成战略合作&#xff0c;通过新一代数据统一化、图谱驱动智能和企业级人工智能&#xff08;AI&#xff09;技术赋能双方客户。 此次合作整合了两大平台的核心优势&#xff0c;将 Altair RapidMiner 平台的强大功能&…