低代碼之光!輕量級(jí) GUI 的設(shè)計(jì)與實(shí)現(xiàn)(輕量化代碼)
前言
每當(dāng)提起低代碼,很多人都會(huì)下意識(shí)的出現(xiàn)過激反應(yīng),吐槽低代碼都是**,唯恐避之不及。可能大部分人覺得低代碼就是替代手寫代碼,對(duì)于程序員來說這是不可接受的。其實(shí)低代碼表述的含義非常寬泛,我相信很多人可能都在低代碼平臺(tái)中受益過,而且確實(shí)可以提升效率。像原型工具(Figma)、建站平臺(tái)(Webflow、Framer)、BI 報(bào)表(Power BI、Looker Studio)、3D 模型搭建(Spline、Womp)、動(dòng)畫編輯器(Rive)等等,這些都是非常有名的一些在線工具。
言歸正傳,本文并不是為了介紹低代碼平臺(tái),也不想評(píng)價(jià)低代碼的好壞,只是想聊一聊低代碼平臺(tái)中 GUI 的設(shè)計(jì)思路和實(shí)現(xiàn)方式。
Acrodata GUI 是一款適用于低代碼平臺(tái)的輕量級(jí) GUI 庫,現(xiàn)已開源。
GitHub: github.com/acrodata/gu…
Playground: acrodata.github.io/gui/playgro…
什么是 GUI
GUI 翻譯為圖形用戶界面,是指采用圖形方式顯示的計(jì)算機(jī)操作用戶界面。在前端編程中,我們一般很少使用 GUI 這樣的描述,所以很多人會(huì)錯(cuò)誤地認(rèn)為 GUI = UI library。
那么到底什么是 GUI 呢?為了便于理解,我們可以參照前端項(xiàng)目中比較有名的 GUI 項(xiàng)目 dat.gui。做過 3D 可視化或者熟悉 ThreeJS 的朋友一定非常熟悉這個(gè)庫。dat.gui 的主要用途就是將配置項(xiàng)轉(zhuǎn)換成圖形化控件,方便調(diào)試參數(shù)。
除了 dat.gui 之外,還有其它幾款 GUI 項(xiàng)目也做得不錯(cuò),tweakpane、lil-gui、leva。
低代碼平臺(tái)中的配置欄
對(duì)于使用過低代碼平臺(tái)或者開發(fā)過類似產(chǎn)品的朋友來說,低代碼平臺(tái)的布局已經(jīng)司空見慣,在布局的右側(cè)通常都是配置欄。當(dāng)然,我們使用的很多軟件也是如此。隨便貼幾張主流工具的截圖。
首先說一點(diǎn),并不是每一款低代碼產(chǎn)品都需要 GUI 生成配置,比如第一張截圖 Webflow,它的所有組件的配置項(xiàng)都是一樣的(全部是 CSS 的可視化配置),這種情況直接寫一個(gè)公共組件可能更簡(jiǎn)單。
但是像第三張截圖 Looker Studio 這樣的產(chǎn)品,每一種圖表組件的配置都不一樣,同時(shí)還允許用戶自定義組件,那么這類產(chǎn)品就非常需要一套靈活易用的 GUI 庫了。
在 Acrodata GUI 的文檔站首頁,我用 GUI 創(chuàng)建了一個(gè)稍微復(fù)雜的 CSS 漸變生成器,它和低代碼平臺(tái)中的配置欄非常類型,歡迎把玩嘗試。
查看 CSS 漸變生成器源碼
輕量級(jí) GUI 的設(shè)計(jì)思路
由于低代碼平臺(tái)的特殊性和復(fù)雜性,GUI 庫在設(shè)計(jì)的時(shí)候必須要保證能組合出任意數(shù)據(jù)結(jié)構(gòu),同時(shí)還要簡(jiǎn)單易用。
基于 JSON 的配置項(xiàng)
為了支持自定義組件,GUI 庫更適合采用 json 數(shù)據(jù)進(jìn)行配置。這和上面提到的 GUI 庫在使用上有很大的不同,我們以 dat.gui 和 Acrodata GUI 為例說明。
假設(shè)某個(gè)組件的配置項(xiàng)如下:
js復(fù)制代碼const options = { content: 'Hello world', opacity: 0.3, visible: false,}
dat.gui 的用法如下:
js復(fù)制代碼const gui = new dat.GUI();gui.add(options, 'content');gui.add(options, 'opacity', 0, 1).step(0.1);gui.add(options, 'visible');
雖然 dat.gui 的用法很簡(jiǎn)潔,但是這種函數(shù)式的聲明方式并不適合動(dòng)態(tài)組件,同時(shí)也不利于數(shù)據(jù)保存。
而在 Acrodata GUI 中的用法則是這樣的:
html復(fù)制代碼<gui-form [config]="config" />js復(fù)制代碼const config = { content: { type: 'text', name: 'content', default: 'Hello world' }, opacity: { type: 'slider', name: 'opacity', min: 0, max: 1, step: 0.1, default: 0.3 }, visible: { type: 'switch', name: 'visible', default: false },}
上面的 GUI 的配置項(xiàng)和組件的配置項(xiàng)的結(jié)構(gòu)是一樣的,只需要將 options 中每個(gè)字段的值轉(zhuǎn)換成 UI 控件的 JSON 聲明即可。
查看更多基礎(chǔ)控件示例
嵌套的數(shù)據(jù)結(jié)構(gòu)
如果要保證 GUI 可以生成任意數(shù)據(jù)結(jié)構(gòu),需要設(shè)計(jì)五種基礎(chǔ)數(shù)據(jù)(string, number, boolean, object, array)的 JSON 配置項(xiàng)的定義格式。上面的例子中已經(jīng)展示了三種基本數(shù)據(jù)類型的定義方式
在 Acrodata GUI 中 object 的定義如下:
json復(fù)制代碼{ "size": { "type": "group", "name": "Size", "children": { "width": { "name": "Width", "type": "number", "default": 1920, "suffix": "px" }, "height": { "name": "Height", "type": "number", "default": 1080, "suffix": "px" } } }}
最后一種數(shù)組類型是最復(fù)雜也是最繁瑣的。常用數(shù)組包含基本數(shù)據(jù)數(shù)組和對(duì)象數(shù)組,同時(shí)每種數(shù)組還要支持?jǐn)?shù)組項(xiàng)的動(dòng)態(tài)刪減。
下面是一個(gè)可動(dòng)態(tài)刪減的對(duì)象數(shù)組的定義方式:
json復(fù)制代碼{ "series": { "type": "tabs", "name": "Series", "default": [ { "id": 1, "name": "bar" }, { "id": 2, "name": "foo" } ], "template": { "name": "No.<%= i 1 %>", "children": { "id": { "type": "number", "name": "ID" }, "name": { "type": "text", "name": "Name" } } } }}
如果對(duì)象數(shù)組的數(shù)組項(xiàng)不相同,則必須搭配 tab 類型來定義:
json復(fù)制代碼{ "misc": { "type": "tabs", "name": "Misc", "children": [ { "type": "tab", "name": "Full Name", "children": { "firstName": { "type": "text", "name": "First Name", "default": "James" }, "lastName": { "type": "text", "name": "Last Name", "default": "Bob" } } }, { "type": "tab", "name": "Contact", "children": { "phone": { "type": "text", "name": "Phone", "default": "5550100" } } } ] }}
查看更多組合控件示例
有了上述五種基礎(chǔ)控件之后,通過嵌套組合就可以生成任意數(shù)據(jù)結(jié)構(gòu)了。
JSON Schema 的局限性
為什么不使用 JSON Schema 呢? 很多人可能覺得使用 JSON Schema 定義 JSON 數(shù)據(jù)會(huì)更規(guī)范也更通用。這種想法是有道理的,但是 JSON Schema 也有一定的局限性。
首先 JSON Schema 只能定義字段的數(shù)據(jù)類型,但是無法定義字段的 UI 類型,所以部分使用 JSON Schema 的動(dòng)態(tài)表單方案還會(huì)加上 UI Schema,比如 react–jsonschema-form。
另外 JSON Schema 的格式較為復(fù)雜,組件的配置項(xiàng)與 JSON Schema 的映射關(guān)系非常不直觀。
基于響應(yīng)式表單構(gòu)建 GUI
Acrodata GUI 是基于 Angular 的響應(yīng)式表單構(gòu)建的,核心代碼只有大約 200 行(查看源碼)。
為了方便在模板中遍歷數(shù)據(jù),首先需要將 GUI config 對(duì)象轉(zhuǎn)換成數(shù)組,同時(shí)使用響應(yīng)式表單的 registerControl 在 FormGroup 的實(shí)例中注冊(cè)所有表單控件。然后在模板中使用響應(yīng)式表單的指令 formGroupName、formControlName、formArrayName 綁定不同 type 的控件就可以了。
Acrodata GUI 使用 Angular Material 作為基礎(chǔ)組件庫,所有樣式和組件都是分模塊導(dǎo)入,所以不會(huì)產(chǎn)生冗余的代碼,其它組件庫也可以使用。
開始使用 GUI 組件
html復(fù)制代碼<gui-form [config]="config" [model]="model" [form]="form" />
config 表示 GUI 的 JSON 配置項(xiàng),不同類型的控件的配置項(xiàng)稍有不同,詳見文檔。除了使用 default 定義控件的默認(rèn)值之外,也可以使用 model(表單值,等同于組件的配置項(xiàng) options)來定義或更新表單的默認(rèn)值,這得益于 Angular 響應(yīng)式表單的 patchValue 方法。
如果你需要監(jiān)聽表單的狀態(tài)或者值變更,可以使用 form 參數(shù),它可以追蹤表單的所有狀態(tài)變化。
ts復(fù)制代碼form = new FormGroup({});this.form.valueChanges.subscribe(v =>{...});this.form.get('opacity').valueChanges.subscribe(v =>{...});
總結(jié)
雖然上面展示的 GUI 功能很強(qiáng)大,但是 GUI 和動(dòng)態(tài)表單并不能完全劃等號(hào),也不是所有的配置項(xiàng)都適合使用 GUI。因?yàn)?GUI 的控件類型有限,而且其本身沒有復(fù)雜的邏輯,所以在低代碼平臺(tái)中要有取舍的使用 GUI 配置。
作者:敘帝利
鏈接:https://juejin.cn/post/7317489364588855307