從0開始搭建低程式碼平臺系列(難點分析)
阿新 • • 發佈:2021-02-04
> 這是如何搭建低程式碼系列的第二篇文章,最近快放假了,所以也不是很忙,所以才能在這段時間連續發2篇,第二篇依舊是比較偏向設計的,也許有人覺得麻煩,其實不是,一個系統只有具備了良好的設計才能具有發展潛力。
# 關於antd渲染結果的分析
因為本次低程式碼是基於antd框架去做的,所有渲染出來的結果的風格和antd類似。為了更加精準的渲染出, 我們想要的效果,所以分析antd是必不可少來的。廢話不多說,上圖。
![](https://img2020.cnblogs.com/blog/1326789/202102/1326789-20210204152916649-1385816413.png)
以一個最基本的篩選框為例子,我們可以發現整體渲染可以分為3層。
第一層,第二層ant-form-item-control-input,ant-form-item-control-input-contet,這是我採用的antd的form元件的渲染結果,每一個都會包一層這個,我們在做ui渲染的時候可以預設渲染上去,所有的渲染預設都是這個樣子的,所以我們可以通過一個統一的入口去加上,比如我這裡就是直接上了一個DOMUtils,自己去包裝的外殼(當然應該還是有其他方案可以探索的)。
第三層開始也就是我們元件需要去渲染的一層了,從這層開始就需要第一篇文章中所提到的,最初設計的資料結構了。下面的程式碼是實現過程中的一個簡單的描述,通過這樣的方式把每一層的結構都描述出來。(懂行的大哥可能會發現這和虛擬dom有點類似,確實我的設想就是描繪一個類似的資料結構,然後我們去解析生成。
也許也有人會有疑問,生成這麼一個結構是否會耗費效能,其實確實會耗費效能,但是我們的樹深度是有限的,最多的不過是4層,所產生的消耗微乎其微。
**dom資料結構**
```tsx
/**
* DOM資料結構
*/
export interface RenderDOM {
domType: string;
type: string;
class?: string;
value?: string;
placeholder?: string;
isDisabled?: boolean;
size?: {
rows?: number,
cols?: number
}; // 顯示行數,多行文字框需要
children?: RenderDOM[]; // 可能存在多層級巢狀(當然也可能是存在多個孩子節點)
}
```
**元件資料結構例項**
```js
{
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: '',
}
]
}
]
}
},
```
說了這麼多,上面看程式碼或許有點抽象,其實它就是一棵樹,一顆多叉樹。
![](http://assets.processon.com/chart_image/5f0c7360e0b34d44f0454314.png)
上圖就是對一個元件渲染的描述,這麼看就簡單了很多。我們需要做的就是採用某種演算法渲染出上訴的div即可,這裡我選擇了dfs,深度優先整好滿足了我的需求。
**渲染路徑如下:**
第一輪:div - div - span - input
第二輪: - span
經過2輪即可完成dom樹的渲染。
# 如何儲存UI資料
這裡確實是個難點,因為資料的儲存效果決定了,這個系統的可擴充套件性,資料結構強大,那麼程式的可擴充套件性也就很強。
這點我暫時準備獨立產生一個UIStoreService對所有的儲存提供服務。
針對這些特色,我們的資料結構設計如下(暫時~這麼設計,後續還會根據不同進行擴充套件)。
```tsx
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層。
![](http://assets.processon.com/chart_image/5fdb29d5e401fd5bc82a8f64.png)
經過這麼一個操作,我們所繪製的元件就被完美呈現在了瀏覽器上了。
# 結尾
今天的文章比較隨意,沒有按照章法來,就想分享一下我關於設計這塊的思路。其實程式碼的話,我已經實現到了繪製UI的階段了,有興趣的童鞋可以找到我的第一篇部落格然後找到對應的程式碼研究