Vue3项目中,如何设计一个表单配置生成器?
前言
大家好,我是林三心,用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心~
背景
最近公司新开了一个 Vue3 的项目,并且让我做了组长,并且交待说可以开发一些基础组件,提高整个团队的开发效率,于是我首先想到的是封装一个表单配置组件,只需要传入配置,就可以生成表单,减少组员的开发负担~
源码+示例:https://github.com/sanxin-lin/all-example/tree/main/form-factory
组员们说以前开发一个表单需要:模板写组件,配置属性,配置规则,获取实例,逻辑分散等等操作,并且每个人都不统一,所以我才决定开发一个统一的表单配置组件~当然这只是一个初步版本,后面会拓展其他新功能的!!!
这个表单配置组件已经在项目中使用了,成员们都觉得大大提高开发效率,因为使用起来真的很简单~初步调研,组员们说效率至少提升了30%!!!!!
具体使用方法如下,其实重要部分就四个部分:
1、表单选项:options 2、表单配置:config 3、表单状态:formState 4、表单实例:formRef
定义完后,传入 FormFactory 组件,便可以生成表单
思考
其实代码不重要,我们要想想,实现这个东西需要注意哪些点,思路是怎么样的,想要看完整源码和示例的,可以看这里
源码+示例:https://github.com/sanxin-lin/all-example/tree/main/form-factory
如何动态生成组件?
比如传入的type: 'input'
就会渲染Input
组件,如果传入type: 'select'
就会渲染Select
组件,要怎么去完成这件事呢?
其实很多人第一时间会想到 Vue 的 <component>
其实一开始我也是使用这种方式去做的,但是发现一个问题,这样去做的话,那么插槽
就做不了了~~
但是不同的 type 对应不同的 组件,这个思路是对的,所以需要维护一个对象
如何渲染插槽呢?
首先每个组件都会有自己的插槽,并且可能会重名,比如 Input 组件有 prefix 插槽,而 Select 也有 prefix 插槽,所以我们要防止冲突,就需要设置别名,比如下面的例子
Input 的 prefix 插槽,我别名成 input_prefix Select 的 prefix 插槽,我别名成 select_prefix
接着只需要把别名插槽放进 FormFactory 里就行了
但是问题是内部的 Input 和 Select 不认 input_prefix 和 select_prefix,所以内部得把 input_prefix 和 select_prefix 转成 Input 和 Select 各自的 prefix
接着,你想要渲染插槽,用模板里的 component 可能有点难做,所以我使用了 Vue 的 h 方法,没有使用模板去做
如何更新状态
内部组件更新值得时候,也要更新传入的 model="formState"
,那么要怎么去做呢?我的做法是监听每一个表单组件的更新事件,然后更新对应的字段,并且要区分 formState 是 ref 还是 reactive,我是使用了 isRef 来判断
这里 reactive 的话我使用了 Object.assign 直接更新表单状态,大家如果有更好的方法的话,可以私信告诉俺下~
多组件库版本
我目前只做了 Ant-Design-Vue 版本,因为项目目前是使用了这个组件库,但是一个好的表单配置,肯定要配置多个组件库,所以我的想法是,设置一个基座,然后每一种组件库都做一个版本,基座通过 provide 把 config、options 传入各个版本中,用 inject 接收,然后拿着配置去做渲染
表单实例暴露
表单的实例 ref 也需要暴露出去,这样才能方便开发者使用表单身上的方法,灵活地对表单进行操作
在基座上,传入 setRef 方法
在各个版本的子项目中去设置实例
总结
思路差不多就是上面那样,至于具体实现可以看下面链接。
源码+示例:https://github.com/sanxin-lin/all-example/tree/main/form-factory
结语
我是林三心
Vue3项目中,如何设计一个表单配置生成器?