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

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


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


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


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


目录
相关文章
|
3月前
|
XML 算法 Java
如何写出让同事无法维护的代码
如何写出让同事无法维护的代码
|
程序员
思考:如何写出让同事难以维护的代码?(1)
思考:如何写出让同事难以维护的代码?(1)
73 0
思考:如何写出让同事难以维护的代码?(1)
思考:如何写出让同事难以维护的代码?(2)
思考:如何写出让同事难以维护的代码?
57 0
思考:如何写出让同事难以维护的代码?(2)
思考:如何写出让同事难以维护的代码?(3)
思考:如何写出让同事难以维护的代码?
52 0
思考:如何写出让同事难以维护的代码?(3)
|
API 计算机视觉
思考:如何写出让同事难以维护的代码?(4)
思考:如何写出让同事难以维护的代码?
72 0
思考:如何写出让同事难以维护的代码?(4)
|
存储 区块链
无聊猿大逃杀游戏卷轴模式系统开发逻辑步骤
区块链的去中心化,数据的防篡改,决定了智能合约更加适合于在区块链上来实现
|
设计模式 SQL Java
有点狠有点猛,我用责任链模式重构了业务代码
文章开篇,抛出一个老生常谈的问题,学习设计模式有什么作用? 设计模式主要是为了应对代码的复杂性,让其满足开闭原则,提高代码的扩展性 另外,学习的设计模式 一定要在业务代码中落实,只有理论没有真正实施,是无法真正掌握并且灵活运用设计模式的 这篇文章主要说 责任链设计模式,认识此模式是在读 Mybatis 源码时, Interceptor 拦截器主要使用的就是责任链,当时读过后就留下了很深的印象(内心 OS:还能这样玩)
|
程序员 API 计算机视觉
思考:如何写出让同事难以维护的代码?doge
本文从【程序命名&注释】【数据类型&类&对象】【控制执行流程】和【程序/结构设计】四个方面梳理了一些真实案例,相信通过这些案例你能迅速get技能:如何写出让同事难以维护的代码doge。
|
编译器 C++
还在因为写项目函数太多而烦恼?C++模板一文带你解决难题
还在因为写项目函数太多而烦恼?C++模板一文带你解决难题
|
开发框架 Java 测试技术
【测试基础】五、这样提bug单,开发小哥还会怼你么?
【测试基础】五、这样提bug单,开发小哥还会怼你么?
【测试基础】五、这样提bug单,开发小哥还会怼你么?