Vue3 項目中,如何設計一個表單配置生成器?
背景
最近公司新開了一個 Vue3 的項目,并且讓我做了組長,并且交待說可以開發(fā)一些基礎組件,提高整個團隊的開發(fā)效率,于是我首先想到的是封裝一個表單配置組件,只需要傳入配置,就可以生成表單,減少組員的開發(fā)負擔~
源碼+示例:https://github.com/sanxin-lin/all-example/tree/main/form-factory
組員們說以前開發(fā)一個表單需要:模板寫組件,配置屬性,配置規(guī)則,獲取實例,邏輯分散等等操作,并且每個人都不統(tǒng)一,所以我才決定開發(fā)一個統(tǒng)一的表單配置組件~當然這只是一個初步版本,后面會拓展其他新功能的?。?!
這個表單配置組件已經(jīng)在項目中使用了,成員們都覺得大大提高開發(fā)效率,因為使用起來真的很簡單~初步調(diào)研,組員們說效率至少提升了30%!?。。?!
具體使用方法如下,其實重要部分就四個部分:
1、表單選項:options
2、表單配置:config
3、表單狀態(tài):formState
4、表單實例:formRef
定義完后,傳入 FormFactory 組件,便可以生成表單
思考
其實代碼不重要,我們要想想,實現(xiàn)這個東西需要注意哪些點,思路是怎么樣的,想要看完整源碼和示例的,可以看這里
源碼+示例:https://github.com/sanxin-lin/all-example/tree/main/form-factory
如何動態(tài)生成組件?
比如傳入的type: 'input'就會渲染Input組件,如果傳入type: 'select'就會渲染Select組件,要怎么去完成這件事呢?
其實很多人第一時間會想到 Vue 的 <component>
其實一開始我也是使用這種方式去做的,但是發(fā)現(xiàn)一個問題,這樣去做的話,那么插槽就做不了了~~
但是不同的 type 對應不同的 組件,這個思路是對的,所以需要維護一個對象
如何渲染插槽呢?
首先每個組件都會有自己的插槽,并且可能會重名,比如 Input 組件有 prefix 插槽,而 Select 也有 prefix 插槽,所以我們要防止沖突,就需要設置別名,比如下面的例子
- Input 的 prefix 插槽,我別名成 input_prefix
- Select 的 prefix 插槽,我別名成 select_prefix
接著只需要把別名插槽放進 FormFactory 里就行了
但是問題是內(nèi)部的 Input 和 Select 不認 input_prefix 和 select_prefix,所以內(nèi)部得把 input_prefix 和 select_prefix 轉(zhuǎn)成 Input 和 Select 各自的 prefix
接著,你想要渲染插槽,用模板里的 component 可能有點難做,所以我使用了 Vue 的 h 方法,沒有使用模板去做
如何更新狀態(tài)
內(nèi)部組件更新值得時候,也要更新傳入的 model="formState",那么要怎么去做呢?我的做法是監(jiān)聽每一個表單組件的更新事件,然后更新對應的字段,并且要區(qū)分 formState 是 ref 還是 reactive,我是使用了 isRef 來判斷
這里 reactive 的話我使用了 Object.assign 直接更新表單狀態(tài),大家如果有更好的方法的話,可以私信告訴俺下~
多組件庫版本
我目前只做了 Ant-Design-Vue 版本,因為項目目前是使用了這個組件庫,但是一個好的表單配置,肯定要配置多個組件庫,所以我的想法是,設置一個基座,然后每一種組件庫都做一個版本,基座通過 provide 把 config、options 傳入各個版本中,用 inject 接收,然后拿著配置去做渲染
表單實例暴露
表單的實例 ref 也需要暴露出去,這樣才能方便開發(fā)者使用表單身上的方法,靈活地對表單進行操作
在基座上,傳入 setRef 方法
在各個版本的子項目中去設置實例
總結(jié)
思路差不多就是上面那樣,至于具體實現(xiàn)可以看下面鏈接。
源碼+示例:https://github.com/sanxin-lin/all-example/tree/main/form-factory