背景
目前低代碼引擎在設(shè)計上是需要在單獨(dú)的頁面上使用的,他的擴(kuò)展功能也都是適用于頁面設(shè)計的。
但是大多數(shù)的場景中,我們都不是只設(shè)計一個頁面,我們還有導(dǎo)航配置、依賴配置、低代碼組件和邏輯編排等等應(yīng)用級別需要的功能。
甚至我們希望在低代碼搭建的過程中能有 VsCode 般絲滑的體驗。快速切換頁面,快速配置應(yīng)用能力等等。而不是現(xiàn)在開發(fā)一個頁面和一個低代碼組件就需要打開至少三個新的標(biāo)簽頁。如果開發(fā)的頁面和組件更多,需要打開的標(biāo)簽頁也就越多。
因此,在使用低代碼平臺時,我的瀏覽器常常就成為了這樣的。
而當(dāng)我們需要在同一個設(shè)計器中,使用兩種不同類型的設(shè)計方式時,只能通過 彈窗 iframe 的方式,這樣的方式體驗上也很不友好。
因此我們需要提供應(yīng)用級別的低代碼引擎,用于低代碼平臺者開發(fā)出應(yīng)用級別的低代碼設(shè)計器。
應(yīng)用級能力介紹
我們這里提供的應(yīng)用級能力是指,在一個設(shè)計器中即可完成低代碼頁面、低代碼組件、應(yīng)用級邏輯、應(yīng)用級國際化配置等的編輯。甚至對于應(yīng)用相關(guān)的配置也可以通過 Webview 的方式進(jìn)行編輯,而不需要來回切換瀏覽器頁面才能達(dá)到這樣的效果。
為了實現(xiàn)這樣的效果,我們在低代碼引擎原有的基礎(chǔ)上新增了以下能力:
- 新增 workspace 模式,新增資源、視圖的概念
- 新增應(yīng)用級擴(kuò)展區(qū)域
- 多層作用域開發(fā)模式
新增 workspace 模式
由于應(yīng)用級別的設(shè)計器和頁面級別的設(shè)計器在開發(fā)時略有不同,所以需要在設(shè)計器初始化時進(jìn)行配置,是否開啟應(yīng)用級別設(shè)計器的模式。
開啟這個模式之后,就需要注冊“資源”和“資源視圖”。
資源
其中,資源是指在應(yīng)用級別的設(shè)計器中,需要一個獨(dú)立的設(shè)計器環(huán)境來進(jìn)行編輯、修改、查看等操作的一份文件,這份文件可能是某一個頁面的 Schema、可能是某一個低代碼組件的 Schema,也可能是一段 JS 邏輯的代碼。
如圖,我們可以在應(yīng)用級別的設(shè)計器中編輯所有注冊的資源,而不用新開多個瀏覽器窗口。
資源類型
其中每個資源所需的設(shè)計器插件、物料、擴(kuò)展的面板可能都是不一樣的,也就是設(shè)計區(qū)域是不一樣的。我們根據(jù)資源所需的設(shè)計器資源將資源分為幾種類型,這里我們稱為資源類型。
如圖,在設(shè)計頁面的時候,使用的資源都是一樣的,這里所有頁面的編輯都會使用頁面的資源類型,而邏輯設(shè)計區(qū)域,可以看到左側(cè)和右邊是沒有注冊擴(kuò)展區(qū)域的,這里就需要一個和頁面不一樣的資源類型,也就是邏輯資源類型。
這樣,根據(jù)資源和資源類型,我們就可以在一個設(shè)計器中編輯和設(shè)計不同類型的低代碼相關(guān)的資源。
資源視圖
在同一個資源中,可以根據(jù)要編輯方式的不同,可能需要使用不同的設(shè)計視圖,因此我們還定義了一個資源視圖的概念,可以給同一個資源注冊不同的視圖,通過切換視圖編輯同一個資源的不同的模塊,來提升整體的編輯體驗。
新增應(yīng)用級擴(kuò)展區(qū)域
為了提供應(yīng)用級別的設(shè)計器,我們新增了一些擴(kuò)展區(qū)域來幫助大家在合適的未來提供應(yīng)用級別的能力。
如圖,在應(yīng)用級別模式下,我們分為應(yīng)用擴(kuò)展、資源擴(kuò)展和視圖擴(kuò)展,其中每種級別擴(kuò)展又提供了不同的擴(kuò)展區(qū)域:
- 應(yīng)用擴(kuò)展:應(yīng)用級別的擴(kuò)展只會在最開始的時候初始化一次,不會因為資源/視圖的切換而重新初始化。
- leftArea:這里用于展示應(yīng)用級別能力的面板,例如:資源管理器,應(yīng)用配置,分支管理等等。
- topArea:這里主要是用于展示應(yīng)用級別的信息,例如:應(yīng)用的名字和圖標(biāo)、應(yīng)用的保存和預(yù)覽、應(yīng)用的國際化配置等等。
- subTopArea:這是和 topArea 類似的區(qū)域,這里主要是用于展示應(yīng)用編輯時的輔助信息,也就是我們的資源切換的標(biāo)簽欄等等。
- 資源擴(kuò)展:資源級別的擴(kuò)展,會在新開資源的時候隨著資源的初始化一起初始化,相當(dāng)于每一個資源都會對應(yīng)一個資源級別的擴(kuò)展區(qū)域,但是在資源視圖切換的時候不會產(chǎn)生變化。
- topArea:這里是資源級別的頂部擴(kuò)展區(qū)域,可以展示一些資源相關(guān)的信息。
- 視圖擴(kuò)展:視圖擴(kuò)展在每個視圖初始化的時候,都會初始化自己的擴(kuò)展區(qū)域。
- leftArea:視圖的左側(cè)擴(kuò)展區(qū)域,一般會展示大綱樹、組件列表等等視圖所需的面板,默認(rèn)會注冊大綱樹的面板。
- topArea:視圖的頂部擴(kuò)展區(qū)域,可以用戶展示對應(yīng)視圖特有的能力。
- mainArea:視圖的編輯區(qū)域
- rightArea:視圖的右側(cè)擴(kuò)展區(qū)域,主要是提供設(shè)計過程中的組件配置能力。
大家可能會擔(dān)心了,有那么多擴(kuò)展區(qū)域,設(shè)計器的畫布豈不會很小。為了解決這個問題,其中大部分?jǐn)U展區(qū)域在沒有注冊的情況下,是不會展示的,也就是低代碼平臺的開發(fā)者可以自行選擇適合自己平臺的擴(kuò)展區(qū)域,而不是使用所有的擴(kuò)展區(qū)域。
多層作用域開發(fā)模式
上面提到的應(yīng)用級別的擴(kuò)展區(qū)域,分為了應(yīng)用層、資源層、視圖層。我們在 API 的設(shè)計和使用上不能再延續(xù)之前的開發(fā)模式了。
在之前的開發(fā)模式下,我們常常會使用如下的代碼來注冊面板,但是這樣的代碼沒有辦法區(qū)分我們的面板是注冊在哪一層的。因此我們需要在原來插件的開發(fā)模式下,根據(jù)插件注冊的位置不同,將作用域分為幾層。
import { skeleton } from "@alilc/lowcode-engine";// 注冊 logo 面板skeleton.add({ area: "topArea", type: "Widget", name: "logo", content: Logo, // Widget 組件實例 contentProps: { // Widget 插件 props logo: "https://img.alicdn.com/tfs/TB1_SocGkT2gK0jSZFkXXcIQFXa-66-66.png", href: "/", }, props: { align: "left", width: 100, },});
因此我們需要在插件的作用域中獲取 skeleton 來進(jìn)行面板的注冊,而不是從全局,也就是從 @alilc/lowcode-engine 中獲取 skeleton API。
import { IPublicModelPluginContext } from '@alilc/lowcode-types';function pluginDemo(ctx: IPublicModelPluginContext) { const { skeleton, } = ctx; return { init() { skeleton.add({ area: 'topArea', type: 'Widget', name: 'pluginDemo', props: { align: 'left', width: 800, }, index: -1, content: Content, contentProps: { ctx, }, }); } }}pluginDemo.pluginName = 'pluginDemo';
這樣,我們在不同的層級進(jìn)行插件注冊,就可以使用不同層級的 skeleton 來注冊對應(yīng)的擴(kuò)展區(qū)域了。
應(yīng)用層
import { init, workspace } from '@alilc/lowcode-engine';(async function main() { workspace.registerResourceType(pageResourceType); await workspace.plugins.register(pluginDemo) init(undefined, { enableWorkspaceMode: true, })})()
如圖,在 workspace.plugins 下注冊的插件,插件下獲取的 skeleton 就是應(yīng)用級別的 skeleton。
資源層
import { IPublicModelPluginContext } from '@alilc/lowcode-types';function pageResourceType(ctx: IPublicModelPluginContext) { return { category: '頁面', defaultViewType: 'page', defaultTitle: window.pageConfig.title, editorViews: [pageView], icon: PageIcon, async init() { await ctx.plugins.register(pluginDemo) }, }}pageResourceType.resourceName = 'page';pageResourceType.resourceType = 'editor';export default pageResourceType;
這樣我們 plugin 里面的 ctx.skeleton 獲取到的就是資源層的 skeleton,可以向資源層注冊擴(kuò)展了。
視圖層
import { IPublicModelPluginContext } from '@alilc/lowcode-types';export const pageView = (ctx: IPublicModelPluginContext, options: any) => { return { async init() { // 注冊插件 await ctx.plugins.register(pluginDemo) }, };};pageView.viewName = 'page';
這樣我們 plugin 里面的 ctx.skeleton 獲取到的就是視圖層的 skeleton,可以向視圖層注冊擴(kuò)展了。
此外,視圖層內(nèi)的 ctx 還可以獲取到其他的 API,來進(jìn)行視圖層設(shè)計器區(qū)域的擴(kuò)展,包括:material、project、simulatorHost、hotkey、setters、canvas 等等。
如何升級應(yīng)用級設(shè)計器
開啟低代碼引擎的應(yīng)用模式
import { init, workspace } from '@alilc/lowcode-engine';(async function main() { // ... init(undefined, { enableWorkspaceMode: true, })})()
注冊應(yīng)用的資源類型和視圖
開發(fā)頁面視圖
import { IPublicModelPluginContext } from '@alilc/lowcode-types';export const pageView = (ctx: IPublicModelPluginContext, options: any) => { return { async init() { // 注冊插件 }, };};pageView.viewName = 'page';
開發(fā)頁面資源類型
import { IPublicModelPluginContext } from '@alilc/lowcode-types';function pageResourceType(ctx: IPublicModelPluginContext) { return { category: '頁面', defaultViewType: 'page', defaultTitle: window.pageConfig.title, editorViews: [pageView], icon: PageIcon, async init() { await ctx.plugins.register(pluginDemo) }, }}pageResourceType.resourceName = 'page';pageResourceType.resourceType = 'editor';export default pageResourceType;
注冊頁面資源類型
import { init, workspace } from '@alilc/lowcode-engine';(async function main() { workspace.registerResourceType(pageResourceType); init(undefined, { enableWorkspaceMode: true, })})()
注意事項
正如上面介紹的,我們需要通過插件的 ctx 作用域來獲取 API,而不是通過全局作用域來獲取 API,否則在多視圖/多資源的情況下,作用域可能會混亂,導(dǎo)致 API 在非預(yù)期的視圖下使用,出現(xiàn)問題。
示例:在下面的 Plugin 中,使用的是全局的 skeleton API,假設(shè) pluginDemo 在 A 視圖中注入的,這也有可能會調(diào)用到 B 視圖的 skeleton API,導(dǎo)致我們的面板注冊到非預(yù)期的視圖中。
import { skeleton } from '@alilc/lowcode-engine';import { IPublicModelPluginContext } from '@alilc/lowcode-types';function pluginDemo(ctx: IPublicModelPluginContext) { return { init() { setTimeout(() => { skeleton.add({ area: 'topArea', type: 'Widget', name: 'pluginDemo', props: { align: 'left', width: 800, }, index: -1, content: Content, contentProps: { ctx, }, }); }, 2000) } }}pluginDemo.pluginName = 'pluginDemo';
未來規(guī)劃
應(yīng)用級別的低代碼平臺落地
接下來我們會在集團(tuán)內(nèi)使用應(yīng)用級別的能力,升級已有的低代碼平臺,將其升級成應(yīng)用級別的設(shè)計器,不斷打磨我們的低代碼平臺和低代碼引擎的應(yīng)用級別的能力,當(dāng)然落地之后也會對外分享我們的經(jīng)驗和教訓(xùn)。
提供應(yīng)用級的精品插件
我們也會開發(fā)更多的應(yīng)用級別的精品插件,幫助大家使用到應(yīng)用級別的設(shè)計器能力。
應(yīng)用級別的設(shè)計器性能優(yōu)化
應(yīng)用級別的設(shè)計器會擁有更多的資源類型,更多的插件,也可以同時編輯多個設(shè)計區(qū)域,后續(xù)對于性能的損耗肯定不低,我們在實踐的同時也需要不斷打磨設(shè)計器的性能。
作者:劉菊萍(絮黎)
來源:微信公眾號:阿里巴巴終端技術(shù)
出處:https://mp.weixin.qq.com/s/dwi40gJjGBHW9MVpag5Oxg
版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn),該文觀點(diǎn)僅代表作者本人。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請發(fā)送郵件至 舉報,一經(jīng)查實,本站將立刻刪除。