抖音"哲玄前端"《大前端全栈实践》里程碑三
核心思想

-
基于领域模型的理念,使用标准 schema 描述整个系统
-
通过 schema 提取有效字段,构建 dtoSchema
-
通过对应的 schema 解析器生成
- table 组件
- search 组件
- 其他各类组件
- api
- 数据库表
- ...(未来拓展)
解决了什么问题
传统前后端开发一个功能时通常的做法是:后端建一张数据库表,写一个接口,前端开发对应的前端页面,存在大量重复的 curd 工作。稍好一点的情况下,会去封装一些组件,但是面对日益增长的需求和系统的复杂度上升,导致组件的业务耦合度上升,不再通用,还是要面对 curd 的问题。
从框架层面出发,有没有什么方式能够解决这个问题?基于领域模型的理念使用一份可配置的 schema 描述文件,正好可以达到这样一种效果,这是一种可行的方案。以数据为驱动,描述一整个站点,而不局限于某一个组件或模块。目标是沉淀 80% 的重复代码,20% 定制化开发能力。程序员从重复的 curd 工作当中解放出来,工作的重心变成搭建一套稳定可维护,拓展性强的系统。对于开发成本的控制,系统的深度建设和横向拓展来说,都是逐步走向一个良性循环当中的
能力
-
能够基于描述文件的配置,快速完成相应功能的生成,对于其他定制功能的支持也可以通过系统的拓展能力快速实现。类似于低代码平台,只是少了拖拉拽这些可视化的操作界面
-
在系统的分层结构中,每一层都具有横向拓展能力
-
组件库/组件化开发
-
模块化开发
-
页面
- dashboard 模板页
- schemaView 沉淀重复代码
- iframeView 接入三方系统
- customView 自定义页面
-
BFF 层
-
api 管理
-
...
-
elpis 领域模型架构
- model 描述了一个 dashboard 的基本情况,基于此利用面向对象的思想(封装,继承,多态)派生出更多的业务场景配置
- 每一个 model 对应 一个 dashboard
DSL 文件字段描述

go
{
mode: 'dashboard' , // 模板类型,不同模板类型对应不一样的模板数据结构
name: '' , // 名称
desc: '' , // 描述
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: '' , // 自定义路由路径
} ,
// 当 moduleType === schema 时
schemaConfig: {
api: '' , // 数据源 API (遵循 restful 规范)'/api/user/'
schema: {
// 板块数据结构
type: 'object' ,
properties: {
key: {
...schema , // 标准 schema 配置
type: '' , // 字段类型
label: '' , // 字段的中文名
// 字段在 table 中的相关配置
tableOption: {
...elTableColumnConfig , // 标准 el-table-column 配置
toFixed: 0 , // 保留小数点后几位
visible: true , // 默认为 true(false 或不配置时,表示不在表单中显示)
} ,
// 字段在 search 中的相关配置
searchOption: {
...elTableColumnConfig , // 标准 el-table-column 配置
comType: '' , // input | select ... 配置组件类型
default: '' , // 默认值
// comType === 'select'
enumList: [] , // 下拉框可选项
// comType === 'dynamicSelect'
api: ''
}
} ,
}
} ,
// table 相关配置
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 配置
}]
} ,
searchConfig: {} , // search-bar 相关配置
components: {} , // 模块组件
} ,
}]
}