這是如何搭建低代碼系列的第二篇文章,最近快放假了,所以也不是很忙,所以才能在這段時間連續發2篇,第二篇依舊是比較偏向設計的,也許有人覺得麻煩,其實不是,一個系統只有具備了良好的設計才能具有發展潛力。
關於antd渲染結果的分析
因為本次低代碼是基於antd框架去做的,所有渲染出來的結果的風格和antd類似。為了更加精准的渲染出, 我們想要的效果,所以分析antd是必不可少來的。廢話不多說,上圖。
以一個最基本的篩選框為例子,我們可以發現整體渲染可以分為3層。
第一層,第二層ant-form-item-control-input,ant-form-item-control-input-contet,這是我采用的antd的form組件的渲染結果,每一個都會包一層這個,我們在做ui渲染的時候可以默認渲染上去,所有的渲染默認都是這個樣子的,所以我們可以通過一個統一的入口去加上,比如我這里就是直接上了一個DOMUtils,自己去包裝的外殼(當然應該還是有其他方案可以探索的)。
第三層開始也就是我們組件需要去渲染的一層了,從這層開始就需要第一篇文章中所提到的,最初設計的數據結構了。下面的代碼是實現過程中的一個簡單的描述,通過這樣的方式把每一層的結構都描述出來。(懂行的大哥可能會發現這和虛擬dom有點類似,確實我的設想就是描繪一個類似的數據結構,然后我們去解析生成。
也許也有人會有疑問,生成這么一個結構是否會耗費性能,其實確實會耗費性能,但是我們的樹深度是有限的,最多的不過是4層,所產生的消耗微乎其微。
dom數據結構
/**
* DOM數據結構
*/
export interface RenderDOM {
domType: string;
type: string;
class?: string;
value?: string;
placeholder?: string;
isDisabled?: boolean;
size?: {
rows?: number,
cols?: number
}; // 顯示行數,多行文本框需要
children?: RenderDOM[]; // 可能存在多層級嵌套(當然也可能是存在多個孩子節點)
}
組件數據結構實例
{
key: 'radio',
name: '單選按鈕組',
type: 'radio',
icon: 'icon-danxuananniuzu',
dom: {
domType: 'div',
type: 'div',
class: 'ant-radio-group ant-radio-group-outline',
children: [
{
domType: 'label',
type: 'label',
class: 'ant-radio-wrapper',
children: [
{
domType: 'span',
type: 'span',
class: 'ant-radio',
children: [
{
domType: 'input',
type: 'radio',
class: 'ant-radio-input',
value: '',
},
{
domType: 'span',
type: 'span',
class: 'ant-radio-inner',
}
]
},
{
domType: 'span',
type: 'span',
value: '',
}
]
}
]
}
},
說了這么多,上面看代碼或許有點抽象,其實它就是一棵樹,一顆多叉樹。
上圖就是對一個組件渲染的描述,這么看就簡單了很多。我們需要做的就是采用某種算法渲染出上訴的div即可,這里我選擇了dfs,深度優先整好滿足了我的需求。
渲染路徑如下:
第一輪:div - div - span - input
第二輪: - span
經過2輪即可完成dom樹的渲染。
如何存儲UI數據
這里確實是個難點,因為數據的存儲效果決定了,這個系統的可擴展性,數據結構強大,那么程序的可擴展性也就很強。
這點我暫時准備獨立產生一個UIStoreService對所有的存儲提供服務。
針對這些特色,我們的數據結構設計如下(暫時~這么設計,后續還會根據不同進行擴展)。
export interface Line {
componentNums: number; // 組件數量
lineStyle: string; // 行樣式
component: {
slider: number; // 組件所站一行的柵欄
componentType: string; // 組件類型
componentName: string; // 組件名稱
styles: string; // 組件樣式
isNeed: boolean; // 是否必填
reg?: string; // 正則表達式
}[];
}
所有的數據都是按行存儲,這樣大大降低了解析難度,同時為了保證一次就能生成可用的文件,我們在加入antd組件的時候,會自動將需要import的組件也設計的渲染模版。這是生成文件的時候會調用~
import `{${
components // 遍歷
}}` from antd
數據存儲完了,我們下一步就是對拿到的數據進行解析了。
這里就呼應了上面提到的UIStoreService這個就是對ui數據進行解析,最后渲染成可運行代碼的地方。
如何精確渲染
因為我們做的低代碼平台,其實對於ui的精確渲染還是有一定的必要的。所以我在第一篇文章中提到了,render分包這么一個概念,這也是做渲染的一種策略,
因為低代碼涉及到的組件比較多,如果按需渲染,精確渲染就成了這類開發着不得不思考的問題,我這里的話計划分組件render,我們將組件分成了3大類。
1.按鈕型
2.輸入型
3.選擇型
分類依據就是根據dom層級來區分。按鈕型普遍都只具有1層dom,輸入型有1到2層,選擇型為3層-4層。
經過這么一個操作,我們所繪制的組件就被完美呈現在了瀏覽器上了。
結尾
今天的文章比較隨意,沒有按照章法來,就想分享一下我關於設計這塊的思路。其實代碼的話,我已經實現到了繪制UI的階段了,有興趣的童鞋可以找到我的第一篇博客然后找到對應的代碼研究下~。