偷偷告诉你们一个坏消息,今天不是周五,哈哈哈!
放了八天假后要连续搬七天砖,真是太累了!抽空来写篇KoalaForm的架构原理,水一下时间🤫🤫🤫
1. Koala Form是什么
对中后台前端来说,开发CURD页面是很常见的事,每个CRUD页面的逻辑都是大同小异。而KoalaForm对CURD进行了场景的抽象,免去了大部分相同的逻辑处理,提效开发。
新同学直接看这里吧 传送门
2. 业界对比
目前业界和KoalaForm比较相似有Sula和Formily.js。
能力 | Sula | Formily.js | Koala Form |
---|---|---|---|
学习成本 | 一般 | 高 | 低 |
开发复杂度 | 高 | 高 | 低 |
UI库支持度 | 低 | 高 | 高 |
可维护性 | 一般 | 高 | 高 |
可复用性 | 一般 | 一般 | 高 |
场景化封装能力 | 有 | 有 | 有 |
用过Sula的都知道,UI扩展有多不好。Formily.js很好很强大,但是上手成本是真的高。
而KoalaForm得益于Vue3的响应式和组合式API,不仅扩展容易,上手成本也低很多。
3. Koala Form架构
从架构图中我们可以看到几个基础的概念:
3.1 字段
我们知道在CURD中,最重要的就是字段,查询需要定义字段,新增、更新也需要字段,列表展示也需要字段,所以在KoalaForm中我们使用Field
来描述字段,主要属性是name、label。name指向的是表单对象的属性,一般也是跟接口API关联的,而label就是表单项字段的名称,展示给用户的。 我们在template上编写字段时,如下指向name和label:
html
<Form ref="formRef" :model="user">
<FormItem label="用户名" prop="userName">
<Input v-model="user.userName"></FInput>
</FFormItem>
</Form>
而使用Field是这样描述:
js
const useField = {
name: 'userName',
label: '用户名',
components: { name: 'Input' }
}
字段提供了很多属性,具体可以参考这里传送门
3.2 组件
在KoalaForm中我们使用ComponentDesc来描述一个组件,可以指定组件名、绑定组件事件,组件属性。 比如<Button type="primary" @click="doClick">点击<Button/>
用组件描述就是这样:
js
const btn = {
name: 'Button',
props: { type: 'primary' },
event: {
onClick: doClick
},
children: '点击'
}
children是组件的子节点,所以我们可以通过组件描述定义出一个页面的组件树。更多属性,具体可以参考这里传送门
3.3 插件
从上面定义的字段来看,并没有定义字段去绑定表单对象,也就是没有v-model="user.userName"
,可是用KoalaForm将该字段渲染时,却已经被绑定了。这里面其实是插件在帮我们做了这件事,因为我们知道这个绑定逻辑就是这么写,不会变,可以把这个收敛到插件中。
插件实际上就是为了解析用户定义的Field和ComponentDesc,所以我们可以通过插件去扩展很多功能,比如vIf、vShow、rules等。可插件将字段和组件解析到哪里去了呢? 这个疑问我们先留着。
3.4 场景
在CURD中比较常用到的是列表、表单、模态框和分页。我们把渲染、操作的逻辑这些分别抽象成场景,提供更便捷的API操作,传入场景定义配置(即SceneConfig),场景执行之后返回场景上下文(即SceneContext)。
在场景中,就是运行插件去收敛逻辑,减轻用户配置。
3.5 行为函数
行为函数是将一系列操作分解成N个单项操作,handler就是单项操作。core中提供的行为函数一般以do开头。
使用时选择合适的handler,并灵活插入一些自定义的操作,组合成一系列完整的逻辑。
比如按查询列表数据可以分解成: 取表单数据 -> 取pager数据 -> 合并处理(自定义) -> 提交获取数据 -> 设置列表数据 -> 设置分页数据
3.6 预设函数
预设函数是获取一些固定的handler组合和场景描述。能快速的辅助场景的配置。一般有UI插件提供,一般以gen开头
比如查询表单,提供预设函数返回固定的查询按钮、重置按钮。
4. 插件的设计
上面提到可插件将字段和组件解析到哪里去了呢?
4.1 状态变化
插件的运行离不开场景,而场景的入参就是字段和组件描述,我们可以称之为初始化态。
我们知道Vue组件渲染之后会生成vNode,虚拟节点。这是就是我们的最终目标,我们可以称之为终态。
vNode是Vue的对象,我们一般不会去操作,也不建议,因此KoalaForm给出了一个中间态:运行时的Scheme。
这个Scheme其实就是一个包含了Vue响应式的对象的一个组件树,我们通过render函数去渲染这个Scheme,转换成vode,而得益于Vue的响应式,Scheme的响应式对象发生变化时,会重新执行render,从而达到更新vNode的目的。如图所示:
4.2 场景上下文
场景会生成上下文,而该场景的Scheme就是放在上下文中,因此插件就是将字段和组件解析到Scheme中,形成该场景的组件树。比如上文中的v-model绑定会被解析到Scheme中的vModels。
js
const scheme = {
component: 'FormItem',
props: { prop: 'userName', label: '用户名 }
vModel
children: [
{
component: "Input",
vModels: {
modelValue: { ref: model, name: 'userName' }
}
}
]
}
到这里我们已经知道了插件的作用和状态的变化,下次我们在聊聊插件怎么去解析字段和组件。
"周五快乐",哈哈哈!