
引題
記得在一次技術分享會上,嘉賓分享了這麼一道公式:
配置模闆 + 資料 = 最終産品。這個公式适用于很多産品,比如電商廣告生成器基于郵件模闆來填充廣告資料生成最終的廣告郵件,比如簡單的設計圖轉成代碼工具基于拆分好的設計圖坑位再填充具體圖檔生成最終的代碼片段。我們知道UForm作為JSON Schema驅動的表單狀态管理器,隻需要有一份json schema資料就能輕易地渲染出表單,那麼隻需要有配置模闆,就可以通過可視化的形式來生成這份json schema,也就有了本文要介紹的可視化表單搭建器。
簡要介紹
為了對下面的内容能夠有一個感官的認知,在這裡先簡要介紹一下可視化搭建工具整體布局以及功能介紹:
- 左側元件集合:單擊/拖拽到預覽區域即可
- 中間預覽區域:編輯态時可以選中元件修改元件配置、删除、拖拽排序;最終預覽态時可看到釋出之後的頁面狀态
- 右側元件配置:選中預覽區域的某個元件進行配置
- 右側上方操作欄
- 預覽:切換中間預覽區域(編輯/最終預覽)兩種狀态
- 儲存:将預覽區域配置好的資料儲存
- 源碼:基于微軟開源的 monaco-editor 實作,對于一些目前可視化無法覆寫或者未實作的都能利用源碼形式實作
黑色主題表單編輯器界面
技術方案
一個好的産品除了要能滿足自身功能需求之外,還需要滿足:可擴充性、元件獨立性等。可視化表單搭建器底層基于UForm渲染,但是UI層能夠根據不同的上層(Antd/Fusion Next)進行特定的适配,同時表單字段元件、屬性配置元件、預覽元件又是互相獨立的,整體再通過Provider包裝起來。
可視化表單搭建器技術方案
技術實作
為了資料能夠在多個元件之間簡單的維護,技術實作上采用了
Redux架構,reducers主要有以下幾個:
- initSchemaData:最核心的reducers,作為最終用于表單渲染的基礎json schema資料
- componentId: 維護目前正在編輯的元件ID
- componentProps: 維護元件的屬性資料,比如name/id/placeholder等資料
- gbConfig: 維護表單全局屬性,比如editable/itemCol等全局屬性
- codemode: 維護是否源碼編輯狀态
- preview:維護是否預覽狀态
同時
components結構上也按照功能拆分了幾個元件:
- fields: 元件類型清單,動态擴充(基于UForm的x-component任意注入元件)
- preview: 核心渲染元件
- props:屬性配置元件
技術難點
Field顆粒度元件的可擴充
可視化表單搭建器是在UForm1.0版本的時候就開始在做了,當時是為了内部的一個項目使用。可視化表單搭建器裡面的很多元件也都是表單,比如:
- 元件的屬性配置(元件name/id/placeholder等屬性)
- 核心預覽子產品(需要實時更新,既能進行拖拽排序/删除等操作也要能切換到最終渲染狀态)
為了減少開發成本以及代碼的可維護性,這部分表單直接用UForm進行渲染,但碰到了一個難點就是同一份json schema, 既要能直接用于渲染表單也要能注入一些HTML标簽用于額外的操作。一開始想簡單暴力用DOM操作強行注入需要的功能,但是這樣子後續維護肯定很不友善,最好的解法是UForm元件支援動态注入,也就是現在開源版本的UForm已經實作的核心功能:
import
關聯處理
表單的關聯是一個最常見的問題,UForm是引入了rxjs來實作時序性的關聯,那可視化搭建器就需要生産出UForm用于關聯的代碼片段。關于可視化的關聯處理感覺可以單獨寫一篇文章來詳細介紹,等後面有時間再詳細讨論。
多層嵌套的拖拽處理
拖拽的實作上用了開源的 react-dnd ,這玩意上手難度感覺不是很簡單,必須要搞懂DragSource/DropTarget這兩個概念才能玩懂。UForm的實作上有布局元件:Layout/Grid/FormItemGrid,在json schema的展現上如下:
映射到可視化配置,其實就是普通元件嵌套在布局元件裡面。基于拖拽的方式就會碰到一個問題:一個布局元件A拖拽到另外一個布局元件B上,是要交換兩者的順序還是把A放到B裡面?這會産生歧義。又或者布局元件A拖拽到布局元件B裡面的普通元件C上,又需要做什麼樣的操作?
目前該問題還在解決中... 有更好的思路請告訴我感激不盡。 當然也想到了另外一種解法,那就是不用拖拽而改用更直覺的箭頭上下方式實作順序交換/縮小樹層級 -- 樹操作,這種也不失為一種好的方式。
現狀及未來規劃
目前該可視化表單配置器用于内部可視化搭建系統以及業務的表單部分生成器,能夠生産出标準的json schema用于上層元件的表單渲染,但是僅實作了最基礎的功能(比如拖拽元件,然後編輯屬性生成一份json schema),很多高階功能還未完全實作(比如表單元件狀态改變的hook自定義接入等)。當然兩個方面的原因導緻目前進度相對比較緩慢:一方面忙于業務沒太多的時間精力投入,另一方面是底層的實作方案可能需要大改是以上層也不太敢動。
未來應該會整體技術重構改造,目前React Hooks其實已經能夠cover住非重度複雜的應用。同時接入更多的自定義流程注入,這樣子才能更好的滿足實際表單的配置需要。