【低程式碼漫談】 lowcode-engine - Vue Renderer 嘗試
highlight: vs2015
導讀
之前《lowcode-engine 協議淺析》這篇文件分析了 lowcode-engine 的協議,有了一定的收穫。但是筆者發現官方只實現了 React 和 Rax 的方案,並沒有 Vue 的方案,而筆者周圍有很多 Vue 的專案,所以需要深入研究一下 lowcode-engine 的實現原理,甚至原始碼,然後嘗試實現一下 Vue Renderer。
正文
React Renderer Demo
官網給的 Demo 效果如下(原文有 bug,經過了修復):
可見,
lowcode-react-renderer
實際上就是暴露出了一個 ReactRenderer
元件,它接收 schema
和 components
兩個屬性,然後就能在頁面當中渲染出結果了,僅此而已。
為了更能夠體現框架無關性,筆者又做了一個純 JS 語法的 Demo,如下:
雖然理論上知道 jsx 就是 JS,但是這樣一些心裡還是更踏實了點。既然是框架無關,那下一步就是實現 Vue Renderer 了,在此之前,我們先來看下 React Renderer 的具體實現。
React Renderer 原始碼
```ts import React, { Component, PureComponent, createElement, createContext, forwardRef, ReactInstance, ContextType } from 'react'; import ReactDOM from 'react-dom'; import { adapter, pageRendererFactory, componentRendererFactory, blockRendererFactory, addonRendererFactory, tempRendererFactory, rendererFactory, types, } from '@alilc/lowcode-renderer-core'; import ConfigProvider from '@alifd/next/lib/config-provider';
window.React = React; (window as any).ReactDom = ReactDOM;
adapter.setRuntime({ Component, PureComponent, createContext, createElement, forwardRef, findDOMNode: ReactDOM.findDOMNode, });
adapter.setRenderers({ PageRenderer: pageRendererFactory(), ComponentRenderer: componentRendererFactory(), BlockRenderer: blockRendererFactory(), AddonRenderer: addonRendererFactory(), TempRenderer: tempRendererFactory(), DivRenderer: blockRendererFactory(), });
adapter.setConfigProvider(ConfigProvider);
function factory(): types.IRenderComponent { const Renderer = rendererFactory(); return class ReactRenderer extends Renderer implements Component { readonly props: types.IRendererProps;
context: ContextType<any>;
setState: (
state: types.IRendererState,
callback?: () => void,
) => void;
forceUpdate: (callback?: () => void) => void;
refs: {
[key: string]: ReactInstance;
};
constructor(props: types.IRendererProps, context: ContextType<any>) {
super(props, context);
}
isValidComponent(obj: any) {
return obj?.prototype?.isReactComponent || obj?.prototype instanceof Component;
}
}; }
export default factory(); ``` 沒錯,原始碼就這些,不到 70 行。Rax Renderer 的原始碼能稍微多一點,所有 5 個檔案加起來 200 多行。很驚訝,很神奇對嗎。這是怎麼做到的呢?這是不是意味著實現 Vue Renderer 也可以很簡單呢?
初看這部分程式碼就做了兩件事:
1. 用 adapter
注入了很多方法,主要分為 setRuntime
、setRenderers
和 setConfigProvider
3 大類;
2. 實現 factory
函式並 default 匯出。
所以很明顯了,下一步就是研究一下 adapter
和 factory
了。
Adapter & Factory
我們先來看一下渲染模組的架構圖:
更多內容見 渲染模組設計。結合架構圖和 React Renderer 的程式碼,我們基本已經捋清了:
- setRuntime 需要注入的,是一些框架相關的最底層的基礎類或函式,也就是框架的基礎能力,比如 React 的 createElement、Component、PureComponent 等。其本質是框架暴露出的底層 API;
- setRenderer 需要注入的,是用 runtime 基礎能力實現的 lowcode-engine 的基礎概念,如 PageRenderer、ComponentRenderer、BlockRenderer 等。其本質其實就是各種元件 Class,只不過是比較基礎的元件;
- setConfigProvider 就是一個載入全域性配置的 Provider,一般是 UI 元件庫提供的能力;
- factory 比較複雜,算是一個高階函式,返回值是一個可以 jsx 的 class。React Renderer 的原始碼我們可以看出,這個 class 繼承了 renderFactory() 返回的類,也繼承了 class Component,然後複寫了一些方法。其它都好理解,關鍵是這個 renderFactory 做了什麼。簡單說,就是利用剛才 adapter 注入的 API 實現渲染邏輯。再具體點,就是載入剛才注入 adapter
中的各種 API,然後按照當前框架的語法,實現 lowcode-engine 各種概念的渲染邏輯,當然還有對 schema 遞迴處理的能力。
撥開迷霧看本質,實際上適配層最重要的就是這個 renderFactory
內部邏輯的實現,其他僅僅是為其提供基礎 API 而已,可以看成是一些封裝好的基礎 utils。而 renderFactory 當中最主要的邏輯就是載入 schema 和 components 然後渲染。那麼怎麼實現 Vue Renderer 呢?
Vue Renderer
很遺憾,目前的結果沒那麼理想。adapter
的程式碼是按照 React 的習慣和邏輯實現的,筆者可以找到 React.createElement
與 Vue.h
是非常相似的,但是其他 API 相差實在是有點大。比如 context 的使用,React 中 createContext/Provider
和 Vue 中的 provide/inject
用法還是有很大差異的。所以實際上只有類 React 框架,比如 Rax 是可以比較方便的接入現有 adapter 層的。要想實現 Vue Renderer,理論上需要把 Vue 的底層 API 加工成 React 的 API,倒不是不可能,但是成本實在太大了,而且也不排除有些 API 根本無法轉換的可能。與其如此,筆者可能會選擇自己實現一個 renderFactory 函式,把解析 schema 和 components 的邏輯,用 Vue 的語法再實現一遍,也就是基本無法複用 @alilc/lowcode-renderer-core
提供的能力了。
而且!而且!而且!這裡還有一個更加重要的問題,那就是現有的視覺化編輯部分是用 React 實現的,這意味著即使實現了 Vue Renderer,你的元件也不能在編輯器的畫布中展示出來,官方也說了短期內不會支援 Vue 畫布。但是 schema + components => 渲染/出碼 這樣的功能還是可以跑通的。
結論
所以最後的結論是:目前要實現 Vue Render 成本非常大。尤其解決視覺化編輯器畫布渲染這塊,有相當大的工作量。
那麼這條路是不是就該放棄了呢?
至少對於筆者來說不是。《lowcode-engine 協議淺析》中也說了,筆者的目的是為了提高開發效率,目標使用者是研發,視覺化編輯並不是必須的功能。所以只要 schema + components => 渲染/出碼 這段功能可以較低成本實現就行。
另外,協議也就是 schema 的確是框架無關的,這個協議是可以 100% 複用的,這就已經是很大的一筆收穫了。最不濟,還可以通過現有視覺化編輯器輸出的 schema,來判斷其元件是如何設計和封裝的,其中最值得參考的就是表單和列表元件,這絕對是一次絕好的偷師機會。
所以接下來筆者計劃就是用 schema + Vue 成功封裝出一個表單元件和列表元件,相信做完這個,離真正的 Vue Render 也就不遠了。
- 看我用 Linux 帶娃,培養程式設計興趣
- 【微前端】Qiankun Vue3 配置
- 通用 Form API 協議 - 基礎版
- Final Form 設計思路淺析
- 【低程式碼漫談】 lowcode-engine - Vue Renderer 嘗試
- Redash 設計理念淺析
- Metabase 設計理念淺析
- DataEase 設計理念淺析
- 開源 BI 工具調研:Superset、Metabase、Redash、DataEase(一)- 基本資料
- Ubuntu 一行命令裝軟體——VirtualBox
- 程式設計師怎麼給娃起名?當然是寫個指令碼!
- GoGoCode - 像用 Jquery 一樣方便地處理 AST
- 【gRPC】Web 請求的 TS 封裝 - 完美版
- 【gRPC】2 分鐘學會 Protocol Buffer 語法
- 【gRPC】封裝前端網路請求的核心思想 - TS版
- 如何避免 Vue 的漏洞破壞單向資料流
- 用函數語言程式設計寫出“傻瓜”都能看懂的程式碼
- Vue3 最佳實踐之編碼規範