“里程碑,三段!”
看着师兄师妹们在合并请求列表文档上密密麻麻的学习进度,少年面无表情,唇角有着一抹自嘲,紧握的手掌,因为懒惰,而导致学习进度比刚进来的师弟师妹们都要缓慢,心里一阵阵钻心的疼痛…
回归正题!!!
什么是DSL
在这几个阶段的学习,一直听到学员们说 DSL DSL,现在终于知道是什么东东了。DSL(领域特定语言,Domain-Specific-Language),就是针对某一特定的领域或业务需求进行设计的计算机语言。
为什么要DSL
可以大大提高开发效率,减少增删改查调用和普通实现组件逻辑,通过简单的配置即可实现大部分业务
怎么用DSL
通过设计好的 schemaJson(“呐呐呐,不懂的同学自己去看文档了哈,这里就不过多展示了”)和对应的模块解析器绘制出对应的页面、组件、服务器、数据等
这里用 dashboard 模型为例
module.exports = {
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 时
iframeConfig: {
path: '', // iframe 路径
},
// 当 moduleType == custom 时
customConfig: {
path: '', // custom 路径
},
// 当 moduleType == schema 时
schemaConfig: {
api: '', // 数据源API(遵循 RESTFUL 规范)
schema: { // 板块数据结构
type: 'object',
properties: {
key: {
...schema, // 标准 schema 配置
type: '', // 字段类型
label: '', // 字段的中文名
// 字段在 table 中的相关配置
tableOption: {
...elTableColumnConfig, // 标准 el-table-column 配置
toFixed: 0, // 保留小数点后几位
visiable: true, // 默认为 true (false 时,表示不在表单中显示)
},
// 字段在 search-bar 中的相关配置
searchOption: {
...eleComponentConfig, // 标准 el-component-column 配置
comType: '', // 配置组件类型 input/select/...
default: '', // 默认值
// comType === 'select'
enumList: [],
// comType === 'dynamicSelect'
api: ''
},
comOption: {},
apiOption: {},
dbOption: {}
},
// 其他字段
}
},
// table 相关配置
tableConfig: {
headerButtons: [
{
label: '', // 按钮中文名
eventKey: '', // 按钮事件名
eventOption: {}, // 按钮具体配置
...elButtonConfig // 标准 el-button 配置
}
],
rowButtons: [
{
label: '', // 按钮中文名
eventKey: '', // 按钮事件名
eventOption: {
// 当 eventKey === 'remove'
params: {
// paramsKey = 参数的键值
// rowValueKey = 参数值 (当格式为 schema::tableKey 的时候,到 table 中找相应的字段)
paramsKey: rowValueKey
}
}, // 按钮具体配置
...elButtonConfig // 标准 el-button 配置
}
]
},
searchConfig: {}, // search-bar 相关配置
comConfig: {}, // 模块组件
apiConfig: {},
dbConfig: {}
}
}]
}
核心实现:menu、schema
1、通过菜单(menu),确定页面要渲染的模块如侧边栏(sider)、嵌套页面(iframe)、自定义页面(custom)、通用页面(schema)
2、通过 schema + config 实现业务,如通过searchBar解析器(searchSchema + searchConfig)实现出搜索栏功能,通过表格解析器(tableSchema + tableConfig)渲染对应的表格内容
配置项过多怎么办?
这里在 dashboard 中配置了一个 hook 文件,用来过滤掉无关配置项,部分核心代码如下
// hook.js
nextTick(() => {
// 构造 tableSchema 和 tableConfig
tableSchema.value = buildDtoSchema(configSchema, 'table');
tableConfig.value = sConfig.tableConfig;
// 构造 searchSchema 和 searchConfig
const dtoSearchSchema = buildDtoSchema(configSchema, 'search');
// 如果网页或路由跳转进入页面时带有条件,需要把条件加上
for (const key in dtoSearchSchema.properties) {
if (route.query[key] !== undefined) {
dtoSearchSchema.properties[key].option.default = route.query[key];
}
}
searchSchema.value = dtoSearchSchema;
searchConfig.value = sConfig.searchConfig;
});
当需要渲染搜索栏和表格时,通过hook把对应的配置项分离出来,过滤掉其他无关配置项,使用时达到页面数据结构单一的效果。
用在什么地方
- 当需要快速搭建一个售前项目用来展示演示时
- 当项目出现多个相同页面、通用页面时,如数据管理系统,后台管理系统等,可以减少重复性代码
- 类似数据的增删改查,如表格、表单、菜单、搜索栏、模块复用、API复用
总结
通过DSL实现设计,减少了接近80%的页面设计,还提供了多个插槽可供页面自定义业务逻辑实现,即20%的客制化友好开发。