此專案是上古專案,程式碼基本很難維護,現在釋出出來僅供參考思路,感興趣的可以根據原理重構一版,實現一個更完備的視覺化編輯
線上例項
xinyu198736.github.io/antd-visual…
託管在 github,第一次載入會比較慢
截圖:
執行
npm run build;
npm run start;
# 因為我不太懂 webpack ,不太會配置,這個專案修改程式碼後實時生效還有問題。。求 pr
複製程式碼
特性
- 視覺化編輯,同時實時生成結果程式碼,還可以單獨預覽
- 豐富的資料編輯能力,可以編輯元件的二維屬性
- 元件可巢狀
- 自適應佈局
- 除了 antd 的元件,還有一些原生 html 元素可使用
原理解析
1.如何實現實時編輯
第一步,抽象整個視覺化工作臺的資料表達,無非是放了一個什麼元件在什麼位置,這個元件的父元件是誰,這個元件的屬性是什麼
如下圖:
一個元件的基礎定義:
title 元件名
type 元件型別(元件真實類名)
can_place 元件是否可以包含子元件
children 元件的子元件,陣列型別
is_native 元件是否是原生 html 元素
config 元件可用的配置資訊
props 元件配置資訊的值,包含樣式和屬性等
複製程式碼
根據這些值,我們就可以渲染和編輯元件了,編輯元件後, 會有一個大的表示畫布當前狀態的資料結構儲存到 state 中, 另外,有一個方法可以根據這個資料結構渲染出整個畫布, 所以每次有任何編輯動作之後,我們會觸發 forceUpdate,重新繪製畫布 也就是說,新增元件,編輯屬性,和畫布的顯示是分離的,中間由一個大的資料結構連線(就是圖片裡這個)
2.如何反向生成 react 程式碼
根據上圖中的資料結構,反向遍歷,可輕易的生成 React 程式碼
3.如何定義元件可用的配置
在 pages/coms/xxx 裡面定義一個元件的可用配置,然後即可在主介面中選擇元件後在右側"屬性編輯區"中編輯屬性。
來看看我們可以定義哪些屬性吧
以一個按鈕為例
export default {
"type": "Button",
"title": "按鈕",
"props": {
type: 'primary', // 定義可以配置的 props
content: '按鈕一隻', // 定義可以配置的 props
style: { // 定義可以配置的樣式
margin: "0px 10px 0px 0px"
}
},
config: { // 可用的配置項
type: { // type 這個配置的描述
text: "主題", // 配置的標題
enum: [ // 可用的列舉,配置時會顯示成下拉框
'primary',
'default',
'dashed',
'danger'
]
},
icon: {
text: "圖示",
},
content: {
text: '文案',
},
style: { // 可用的樣式配置
width: {
text: "寬度",
},
margin: {
text: "外邊距",
type: "4-value" // 一種定製型別,會渲染成 4 個輸入框
}
}
},
}
複製程式碼
這是最基本的配置項,只能適用於最基本的元件,但是遇到像 table 或者 Breadcrumb 這種元件就不行了
4.高階配置(二維資料)
以 Breadcrumb 為例,他有一個資料來源的屬性,資料來源是一個陣列+物件的混合表達,這種元件不少,應該如何定義呢
export default {
"type":"Breadcrumb",
"title":"麵包屑",
props:{
routes:[ // 這裡是資料來源的屬性,和預設值
{
breadcrumbName:"一級目錄",
path:"#",
key:1
},
{
breadcrumbName:"二級目錄",
path:"#",
key:2
}
]
},
config:{
routes:{ // 如何表達這個屬性應該如何配置
text:"專案配置",
enumobject:[{ // 一種新的型別,enumobject,物件列舉
key:1,
dataIndex:"breadcrumbName", // 列舉的物件的第一個 key 是什麼
title:"顯示文字", // 列舉的物件的第一個 key 的文字描述
type:'String', // 列舉的物件的第一個 key 的型別
},{
key:2,
dataIndex:"path", // 列舉的物件的第二個 key 是什麼
title:"連結", // 列舉的物件的第二個 key 的文字描述
type:'String', //列舉的物件的第二個 key 的型別
}]
}
}
}
複製程式碼
最終的屬性編輯區:
即可邊界物件列舉屬性
5.更復雜的元件
大家會發現,table 這種元件和上述的元件都不太一樣,首先看純資料表格
其實這裡還好,只是 table 有兩個屬性,一個表達列的資料,一個表達行的資料,我們只需要兩個物件列舉即可
{
config:{
columns:{
text:"列管理",
enumobject:[
{
title: '列文字',
dataIndex: 'title',
type:"String"
},
{
title: '列key',
dataIndex: 'dataIndex',
type:"String"
}
]
},
dataSource:{
text:"值管理",
enumobject:{
type:'relative_props_object',
target:'columns'
}
}
}
}
複製程式碼
這裡實現了一個 關聯,可以把 dataSource 的配置和 columns 關聯起來 (relative_props_object)
6.更更復雜的表格
如果只是資料,還好, 但是 table 裡可以還可以巢狀其他元件,每行每列,想想是不是頭疼。。如下圖
table 的每個 column 其實可以定義內部顯示的元素,我們在預設值裡就給他塞一個空的 layout 進去, 這樣之後這裡就會變成一個可以放置其他子元素的坑,具體不展開了,這裡的邏輯比較複雜。