低代碼之光!輕量級 GUI 的設(shè)計(jì)與實(shí)現(xiàn)

cover

前言

每當(dāng)提起低代碼,很多人都會下意識的出現(xiàn)過激反應(yīng),吐槽低代碼都是**,唯恐避之不及??赡艽蟛糠秩擞X得低代碼就是替代手寫代碼,對于程序員來說這是不可接受的。其實(shí)低代碼表述的含義非常寬泛,我相信很多人可能都在低代碼平臺中受益過,而且確實(shí)可以提升效率。像原型工具(Figma)、建站平臺(Webflow、Framer)、BI 報(bào)表(Power BI、Looker Studio)、3D 模型搭建(Spline、Womp)、動畫編輯器(Rive)等等,這些都是非常有名的一些在線工具。

言歸正傳,本文并不是為了介紹低代碼平臺,也不想評價(jià)低代碼的好壞,只是想聊一聊低代碼平臺中 GUI 的設(shè)計(jì)思路和實(shí)現(xiàn)方式。

Acrodata GUI 是一款適用于低代碼平臺的輕量級 GUI 庫,現(xiàn)已開源。

GitHub: https://github.com/acrodata/gui
Playground: https://acrodata.github.io/gui/playground

什么是 GUI

GUI 翻譯為圖形用戶界面,是指采用圖形方式顯示的計(jì)算機(jī)操作用戶界面。在前端編程中,我們一般很少使用 GUI 這樣的描述,所以很多人會錯(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

除了 dat.gui 之外,還有其它幾款 GUI 項(xiàng)目也做得不錯(cuò),tweakpanelil-gui、leva

低代碼平臺中的配置欄

對于使用過低代碼平臺或者開發(fā)過類似產(chǎn)品的朋友來說,低代碼平臺的布局已經(jīng)司空見慣,在布局的右側(cè)通常都是配置欄。當(dāng)然,我們使用的很多軟件也是如此。隨便貼幾張主流工具的截圖。

Webflow
Spline
Looker Studio

首先說一點(diǎn),并不是每一款低代碼產(chǎn)品都需要 GUI 生成配置,比如第一張截圖 Webflow,它的所有組件的配置項(xiàng)都是一樣的(全部是 CSS 的可視化配置),這種情況直接寫一個(gè)公共組件可能更簡單。

但是像第三張截圖 Looker Studio 這樣的產(chǎn)品,每一種圖表組件的配置都不一樣,同時(shí)還允許用戶自定義組件,那么這類產(chǎn)品就非常需要一套靈活易用的 GUI 庫了。

在 Acrodata GUI 的文檔站首頁,我用 GUI 創(chuàng)建了一個(gè)稍微復(fù)雜的 CSS 漸變生成器,它和低代碼平臺中的配置欄非常類型,歡迎把玩嘗試。

Acrodata GUI

?? 查看 CSS 漸變生成器源碼

輕量級 GUI 的設(shè)計(jì)思路

由于低代碼平臺的特殊性和復(fù)雜性,GUI 庫在設(shè)計(jì)的時(shí)候必須要保證能組合出任意數(shù)據(jù)結(jié)構(gòu),同時(shí)還要簡單易用。

基于 JSON 的配置項(xiàng)

為了支持自定義組件,GUI 庫更適合采用 JSON 數(shù)據(jù)進(jìn)行配置。這和上面提到的 GUI 庫在使用上有很大的不同,我們以 dat.gui 和 Acrodata GUI 為例說明。

假設(shè)某個(gè)組件的配置項(xiàng)如下:

const options = {
  content: 'Hello world',
  opacity: 0.3,
  visible: false,
}

dat.gui 的用法如下:

const gui = new dat.GUI();

gui.add(options, 'content');
gui.add(options, 'opacity', 0, 1).step(0.1);
gui.add(options, 'visible');

雖然 dat.gui 的用法很簡潔,但是這種函數(shù)式的聲明方式并不適合動態(tài)組件,同時(shí)也不利于數(shù)據(jù)保存。

而在 Acrodata GUI 中的用法則是這樣的:

<gui-form [config]="config" />
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 的定義如下:

{
  "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ù)組和對象數(shù)組,同時(shí)每種數(shù)組還要支持?jǐn)?shù)組項(xiàng)的動態(tài)刪減。

下面是一個(gè)可動態(tài)刪減的對象數(shù)組的定義方式:

{
  "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"
        }
      }
    }
  }
}

如果對象數(shù)組的數(shù)組項(xiàng)不相同,則必須搭配 tab 類型來定義:

{
  "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ù)會更規(guī)范也更通用。這種想法是有道理的,但是 JSON Schema 也有一定的局限性。

首先 JSON Schema 只能定義字段的數(shù)據(jù)類型,但是無法定義字段的 UI 類型,所以部分使用 JSON Schema 的動態(tài)表單方案還會加上 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 對象轉(zhuǎn)換成數(shù)組,同時(shí)使用響應(yīng)式表單的 registerControlFormGroup 的實(shí)例中注冊所有表單控件。然后在模板中使用響應(yīng)式表單的指令 formGroupNameformControlName、formArrayName 綁定不同 type 的控件就可以了。

Acrodata GUI 使用 Angular Material 作為基礎(chǔ)組件庫,所有樣式和組件都是分模塊導(dǎo)入,所以不會產(chǎn)生冗余的代碼,其它組件庫也可以使用。

開始使用 GUI 組件

<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)變化。

form = new FormGroup({});

this.form.valueChanges.subscribe(v =>{...});
this.form.get('opacity').valueChanges.subscribe(v =>{...});

總結(jié)

雖然上面展示的 GUI 功能很強(qiáng)大,但是 GUI 和動態(tài)表單并不能完全劃等號,也不是所有的配置項(xiàng)都適合使用 GUI。因?yàn)?GUI 的控件類型有限,而且其本身沒有復(fù)雜的邏輯,所以在低代碼平臺中要有取舍的使用 GUI 配置。

如果你喜歡 Acrodata GUI 或者有更好的想法,歡迎和我交流!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容