为什么会存在重复的工作?
在学习这一章节的时候,这个问题从一开始就已经摆出来了,随着逐步的学习,开始反思之前的工作内容,总是在进行重复的开发流程,感觉每天都很忙,日报都写的满满当当,但细细一琢磨,写满了重复两个字,中间有为了减轻工作量,对table表格进行了封装,把常用的导出,删除,显隐,分页功能进行了组合,减少了一部分工作量,但仍然无法避免还是存在大量的重复劳动
怎么避免重复的工作
封装通用的公共组件,这是一个好办法,但是依然还是显得不够用,不同的产品必然会有不同的想法,这样一个本来通用的公共组件随着项目的推进也会变得不通用,那么这时候我们就需要来构造一个更广的通用平台,以一个规范的开发平台来倒推我们的产品,抽离出公共部分,形成一个固定的模板,这样只需要进行配置就可以生成不同的页面,节省了大量的开发时间
公共部分的生成
首先,我们这边有一个后台管理系统,大家应该都有过类似的开发经历,一个后台管理系统的重复内容可以说是非常多的,基本都是一个菜单+可能存在的子菜单+页面内容,大部分的页面内容都是一个查询栏+一个列表,这个我们完全可以直接复制,改改相应字段就开发完成了,是不是很简单?那我们为什么不能更简单呢?抽离出菜单和页面内容展示区域或者说更多的公共部分,形成一个约定的配置,通过自定义的语言规则写出一份DSL脚本,通过脚本来生成想要达到的内容
DSL的生成
DSL(领域特定语言,Domain-Specific-Language),就是针对某一特定的领域或业务需求进行设计的计算机语言,我们这边通过特定的schemaJson和相对应的模块解析器自动生成页面,组件,服务器,数据等,这边有一份配置模板,
mode: "dashboard"; //模板类型,不同模板类型对应不一样的模板数据结构
name: ""; //名称
desc: ""; //描述
icon: ""; //icon
homePage: ""; //跳转首页
//头部菜单
menu: [
{
key: "", //菜单唯一值
name: "", //菜单名称
menuType: "", //枚举值,group/module
//当menuType==group时,可填
subMenu: [
{
//可递归menuItem
},
],
//当menuType==module时,可填
moduleType: "", //枚举值:sider/iframe/custom/schema
//当moduleType==sider时
siderConfig: {
menu: [
{
//可递归menuItem(除了moduleType==sider)
},
],
},
//当moduleType==iframe时
iframConfig: {
path: "", //iframe路径
},
//当moduleType==custom
customConfig: {
path: "", //自定义路由
},
//当moduleType==schema时
schemaConfig: {
api: "", //数据源API(遵循RESTFUL规范)
schema: {
//板块数据结构
type: "object",
properties: {
key: {
...schema, //标准schema配置
type: "", //字段类型
label: "", //字段中文名
// 字段在table中的相关配置
tableOption: {
...elTableColumnConfig, //el-table-column相关配置
visible: true, //字段是否在table中展示,默认为true(false表示不在表单展示)
},
// 字段在search-bar中的相关配置
searchOption: {
...eleComponentConfig, //标准el-component-column 配置
comType: "", //配置组件类型 input/select/...
default: "", //默认值
// comType=='select'
enumList: [], //下拉框可选项
// comType=='dynamicSelect
api: "",
},
},
},
},
},
tableConfig: {
headerButtons: [
{
label: "", //按钮中文名
eventKey: "", //按钮事件名
eventOption: {}, //按钮具体配置
...elButtonConfig, //el-button相关配置
},
], //表格头部按钮配置
rowButtons: [
{
label: "", //按钮中文名
eventKey: "", //按钮事件名
eventOption: {
// 当eventKey=='remove'时
params: {
//paramKey=参数键值,rowValueKey=参数值(当格式为schema::tableKey时,到table中找相应字段)
paramKey: rowValueKey,
},
}, //按钮具体配置
...elButtonConfig, //el-button相关配置
},
], //表格行按钮配置
}, //table相关配置
searchConfig: {}, //searchBar相关配置
components: {}, //模块组件
},
];
}
上面是一份模板案例,我们可以看到它从定义菜单开始,配置每个模块,如果后续有需要新增的内容,直接新增相关schema配置即可
DSL的实现
在上文,我们有了一份配置模板,那我们就需要去实现它,为了规范化,同时也为了简化用户的使用成本,我们需要对代码有一定的约束,对此,我们应当在一个统一目录下进行相关配置,在elpis这个项目中,我们规定在elpis/model目录下配置DSL,目录结构如下
model文件夹下分为business和course两个子文件夹和index.js文件,index.js文件中的方法主要用来处理model和project的配置并进行合并,最后返回一份DSL数据结构,处理思路大致如下:
- project有的键值,model也有=》修改
- project有的键值,model没有=》新增
- model有的键值,project没有=》保留
business和couse两个文件夹则分别是电商板块和课程板块两个不同的dsl,两个不同的dsl下分别配置了不同的model及项目的个性化配置,均通过index.js输出相应的数据结构,然后我们通过在service层调用接口,拿到返回数据去生成页面
页面的相关结构
上图是页面的约定好的目录结构,project-list是应用入口,dashboard下是各个模板页,根据不同的dsl生成不同页面
通过dsl配置及schema的开发,可以提炼出80%左右的重复工作量,剩下的也可以在我们项目中的custom-view实现
本文内容来自于抖音 哲玄前端