【源码共读】组件太多,重复工作量大?这次一行命令带你解放双手!

简介: 【源码共读】组件太多,重复工作量大?这次一行命令带你解放双手!


tdesign-vue的源码,有一个初始化的脚本文件,script/init/index.js,在这个文件中,就是这个文件让他拥有了动态创建组件和删除组件的能力。


今天通过学习这个工具的源码,来学习一下如何动态创建组件,让我们也可以在项目中使用这个功能。


源码地址:

使用


README.md中并没有关于这一块的使用说明,我们直接通过源码来看如何使用。


打开script/init/index.js文件,直接拉到最底下,可以看到下面的代码:


         

最底下看到直接执行了init()函数,在init函数中,看第一行代码就知道这个是运行在node环境下的,因为process.argvnode环境下的全局变量,用来获取命令行参数。


然后再看package.json文件,可以看到script中有一个init命令,这个命令就是用来执行script/init/index.js文件的。


         

可以省略index.js,因为node会默认去找index.js文件


通过这些线索,我们可以知道运行这个脚本的命令是:


         


效果都是一样的,都是执行script/init/index.js文件,然后传入两个参数,第一个参数是组件名,第二个参数是del,如果传入了del,就会删除组件,如果没有传入del,就会创建组件。


注意:不能cdscript/init目录下执行,因为这样node的执行目录就是script/init目录,而不是项目根目录,所以会找不到src目录


源码分析


动态创建组件

1. 创建组件

上面我们已经知道了,如果不传入del,那就现从创建组件开始分析,先简化一下代码:


         

首先可以看到component是必传的,如果不传直接退出程序。


indexPathsrc/index.ts文件的路径;


toBeCreatedFiles是通过config.getToBeCreatedFiles(component)获取的,来看看这个函数:


         

这个在script/init/config.js文件中;


可以看到这个函数返回了一个对象,这个对象的键是目录,值是文件,这个对象的目的就是用来动态创建组件的。


比如我们传入的组件名是Button,那么这个函数就会返回一个对象:


         

继续往下看,addComponent函数:


         

这个就是用来给组件创建目录和文件的,首先会遍历toBeCreatedFiles对象,然后创建目录,然后创建文件。


代码太多,先简化一下:


         

上面的简化只是将入参固定,移除了最外层的遍历,在外面循环执行我这个简化的函数也是可以的,然后将fs.mkdir改成了fs.mkdirSync,这样看着会更清晰一些。


可以看到最后会遍历contents.files,然后根据item的类型来创建文件,如果是对象,那么就会调用outputFileWithTemplate函数,这个函数的作用是根据模板创建文件:


         

简化代码,将入参固定:


         

可以看到,这个函数会读取模板文件,然后编译模板,然后传入模板变量,最后创建文件。


_.templatelodash的一个方法,传入模板字符串,返回一个编译函数,然后调用这个函数传入模板变量,就可以得到编译后的字符串。


模板文件长这样:


         

就是通过<%= xxx %>这种形式来引用模板变量,然后lodash.template返回的编译函数就会把这些变量替换掉。、


这里面有两个模板变量,componentupperComponent


  • component就是组件名


  • upperComponent见名知意,就是组件名的首字母大写,是通过getFirstLetterUpper函数来实现的:

         

非常简单的一个函数,就是把首字母大写,然后拼接上剩下的字符串。


继续往下就是创建文件了,调用了createFile函数:


         

就是调用fs.writeFile来创建文件,这里面有两个参数,一个是文件路径;


desc用于打印日志,这里面会打印出文件的描述,然后文件的路径。


回到addComponent函数,可以看到item如果不是对象,就直接调用createFile函数来创建文件,不过内容是空的;


部分代码:


         

addComponent函数执行完毕,就会在node执行脚本的目录下创建一个src目录,然后里面会生成一堆文件:

image.png

这一步只是创建,接下来就是注册组件了。


2. 注册组件


上面执行完addComponent函数后,还有一个insertComponentToIndex函数,这个函数的作用就是把组件注册到index.js文件中:


         

第一行就是将首字母大写,刚才已经讲过了,先把代码整理一下:


         

importPath是通过getImportStr函数来获取的,这个函数的作用就是拼接import语句:


         

这里会判断index.ts文件中是否已经存在了该组件,如果存在就不再插入,否则就会在index.ts文件中插入import语句和组件名。


然后找到入口文件的import语句,分号结尾,后面有两个换行符,然后在后面插入import语句:


         

然后找到components对象,然后在后面插入组件名:


         

最后写入文件,就完成了组件的注册。


删除组件


最开始的init函数还有一个删除的分支,回顾一下:


         

上面还是简化后的代码,删除逻辑也一样,两个函数完成,先来看deleteComponent函数:


         

这次就不简化代码了,可以自行尝试一下;


先看第一行代码,这里会获取快照文件,通过getSnapshotFiles函数:


         

这个快照信息的结构和toBeCreatedFiles是一样的,然后和toBeCreatedFiles合并;


然后遍历合并后的对象,如果有deleteFiles属性,就删除这些文件,否则就删除整个文件夹;


可以看一下配置文件,是没有deleteFiles属性的,所以这里就是删除整个文件夹;


deleteFolderRecursive函数是在utils文件中定义的,代码如下:


         

这里就是递归删除文件夹,如果是文件就直接删除,如果是文件夹,就递归删除;


fs.unlinkSync是删除文件,fs.rmdirSync是删除文件夹;


然后还要删除index.ts文件中的组件注册信息,这里就是deleteComponentFromIndex函数:


         

实现逻辑和注册组件的时候是相同的,只不过注册组件是增加,删除组件就是删除,主要是下面这一段代码:

js


         

这里是用正则匹配要删除的内容,然后替换为空字符串,就完成了删除组件的操作。


自己动手


上面其实并不是很复杂,我们自己也可以实现一个类似的功能,就比如我们日常开发中,经常会做重复的CRUD操作,我们可以封装一个脚手架,来帮助我们完成这些重复的操作;


首先分析需求,我们需要做的事情是:


  1. 有哪些层级的文件夹需要创建;
  • src/api:接口层;
  • src/pages:页面层;
  1. 每个文件夹下需要创建哪些文件;
  • src/api增删改查四个接口
  • src/pages:列表页面,有增删改查四个功能
  1. 每个文件需要写入哪些内容;
  • src/api增删改查四个接口
  • src/pages:列表页面,有增删改查四个功能
  • src/router.js:路由配置

我这里就简单的实现一下:


  • template 文件夹

  • api.js

         
  • pages.vue

         

  • router.js

         

上面两个文件是模板文件,router.js是本来就应该存在的。

现在开始实现:

  • init.js

         

这样我们就可以通过命令行来生成模板文件了。


         

上面的代码没有经过测试,可能有问题,只是跟着思路写的,正则是测试过的没问题,有一颗开源的心但是懒,愿意可以自己完善一下。

总结


通过tdesign-vue的动态注入组件的源码,学习到了通过模板文件来生成代码的思路,对于一些重复性的工作,可以通过这种方式来减少重复性的工作,提高效率。


对应动态修改文件内容,也提供了一个思路,通过正则匹配,然后替换,这样就可以动态修改文件内容了。


正则确实有点烧脑,换我的话,我应该会用注释内容当做一个占位符,然后直接找到这个占位符,通过占位符来定位替换的位置,这样就可以减少很多心智上的负担了,缺点就是担心协助被误删。


目录
相关文章
|
2天前
|
设计模式 算法 程序员
程序员为何需要反复修改Bug?探寻代码编写中的挑战与现实
作为开发者,我们在日常开发过程中,往往会遇到反复修改bug的情况,而且不能一次性把代码写的完美无瑕,其实开发项目是一项复杂而富有挑战性的任务,即使经验丰富的程序员也难以在一次性编写完美无瑕地完成代码,我个人觉得一次性写好代码是不可能完成的事情。虽然在设计之初已经尽力思考全面,并在实际操作中力求精确,但程序员仍然需要花费大量时间和精力来调试和修复Bug。那么本文就来分享程序员需要反复修改Bug的原因,以及在开发中所面临的复杂性与挑战。
60 1
程序员为何需要反复修改Bug?探寻代码编写中的挑战与现实
|
2天前
|
算法 程序员
为何程序员在编写程序时难以一次性将所有代码完美无瑕地完成,而是需要经历反复修改Bug的过程?
为何程序员在编写程序时难以一次性将所有代码完美无瑕地完成,而是需要经历反复修改Bug的过程?
20 7
|
8月前
|
安全 测试技术
不会写测试用例咋办?牢记这5点,你也能写出高逼格案例
不会写测试用例咋办?牢记这5点,你也能写出高逼格案例
|
11月前
|
设计模式 存储 JavaScript
🙅‍都说太多if...else不好,那有没有可以直接抄的改造方案呢?
开发过程中,经常遇到大量的if...else逻辑,这使得代码复杂、难以维护。但别担心!这里会引导你走出这个困境!
82 0
|
编译器 C++
还在因为写项目函数太多而烦恼?C++模板一文带你解决难题
还在因为写项目函数太多而烦恼?C++模板一文带你解决难题
|
设计模式 SQL Java
有点狠有点猛,我用责任链模式重构了业务代码
文章开篇,抛出一个老生常谈的问题,学习设计模式有什么作用? 设计模式主要是为了应对代码的复杂性,让其满足开闭原则,提高代码的扩展性 另外,学习的设计模式 一定要在业务代码中落实,只有理论没有真正实施,是无法真正掌握并且灵活运用设计模式的 这篇文章主要说 责任链设计模式,认识此模式是在读 Mybatis 源码时, Interceptor 拦截器主要使用的就是责任链,当时读过后就留下了很深的印象(内心 OS:还能这样玩)
|
Java C语言
看似无害的代码如何搞垮系统
编程就像魔法。最近遇到一个诡异的问题:添加一段看似无害的简单代码后,系统原有功能不可用了。 ## 复现演示 jdk 8 可使用如下演示代码复现这个问题。 `TaskCenter` 是一个任务框架,可添加多个任务,随后框架将执行这些任务。 `First` 任务是新增代码,看起来简单无害,且看不出对原有任务 `Count` 有何影响,但添加 `First` 任务后,其自身执行正常,原本正常的 `C
102 0
|
开发框架 Java 测试技术
【测试基础】五、这样提bug单,开发小哥还会怼你么?
【测试基础】五、这样提bug单,开发小哥还会怼你么?
【测试基础】五、这样提bug单,开发小哥还会怼你么?
|
前端开发 JavaScript 测试技术
为了降低维护成本(早点下班),我在组件开发中所做的那些优化(偷懒)
组件开发中为了稳定性、健壮性,经常需要为组件编写测试用例,然后还要为了开发者方便使用编写文档,都是非常耗时间的差事。作为一个独立维护组件库的程序员,为了能够降低组件维护的成本(早点下班),我总结了一下自己过去几年为了让组件开发更加高效所做的那些事情(偷的那些懒)。
|
运维 监控 前端开发
程序员告别 996 第一步:1 人搞定一个项目,摆脱“重复造轮子”
程序员告别 996 第一步:1 人搞定一个项目,摆脱“重复造轮子”
206 0
程序员告别 996 第一步:1 人搞定一个项目,摆脱“重复造轮子”

热门文章

最新文章