本文主要介紹了基於 React 構建可視化編輯平臺的實踐,包括對可視化拖拽佈局、在線編輯、同構直出的實現。css
目前,咱們的校園在線招聘業務有大量的企業定製化需求,企業在英才校園作招聘,同時也但願有本身的招聘主頁,每一年都會招聘一部分兼職同窗來開發這類的招聘主頁,這類招聘主頁一般不復雜,可是若是所有須要前端同窗實現的話,仍是很耗時費力的,咱們但願能經過技術手段不斷的提高這類業務的交付效率。前端
定製頁相關的項目,早期是經過靜態頁來作的,純靜態頁對開發者來講上手容易,可是很難作組件化,上線流程徹底靠手工,成本過高,因此咱們計劃逐步推動經過可視化編輯提高效率。數據庫
項目總體分了兩期:後端
一期,實現了可視化的在線編輯、發佈,支持流式佈局、絕對定位佈局、同構直出、動畫,提供了通用的組件庫。前端框架
二期,支持組件可擴展,提供組件開發工具,組件市場,三期仍在完善階段,暫未發佈。服務器
首先看下咱們的系統演示,而後再逐步分析深刻,主要是可視化編輯系統開發思路,以及關鍵模塊的實現。數據結構
針對可視化編輯平臺,咱們作了一些調研,有一些思想咱們以爲挺有意義,這裏分享一下,參考文章見參考文獻。框架
咱們的系統,對標上面的維度應該下面三項:less
Component Tree 編輯,核心功能爲頁面可視化佈局設計異步
頁面由組件組成,組件能夠支持嵌套,目前組件是通用的組件,後期會支持擴展,組件能夠承載業務邏輯。
提供了拖拽佈局支持,支持流式佈局,絕對定位佈局。
前端小白,核心訴求是交互性高,所見即所得的編輯方式
目前是組內兼職的同窗在用,有必定的前端佈局基礎,理解每一個組件的使用方式。
若是想下降對用戶的要求,好比對普通用戶,那麼就要提供模板支持,對普通用戶而言,改改背景圖,換個圖片,編輯下文字就夠用了,越是要下降對用戶的要求,越是要固化一些設計和數據模型。
前端框架組件,依賴工具提供組件,編輯效率高,業務邏輯封裝度高
目前系統的自由度是組件級別,內置了通用的組件,包括:
這些組件是內置到系統的,二期的組件市場,目標是組件可擴展,組件能夠承載業務,業務邏輯封裝度更高些,方便使用。
系統採用技術棧以下:
前端:React + Redux + ImmutableJs + ReactDND + Antd
後端:Node Express + MongoDB + Redis
可視化佈局
首先,須要定義渲染UI的數據結構,一般這種UI的數據都是樹形的結構,能夠用一個大的 JSON 來表示,而後遞歸渲染。
相似以下的結構:
節點使用相似 React 的虛擬 DOM 結構:
因爲直接使用樹形的的結構,對節點的增刪改查不友好,全部進行了扁平化處理,將樹拆成了兩個結構:
結構一:
存儲節點的關係,相似一個數據庫的二維表,描述節點的父子關係,方便修改父子結構,同級排序。
結構二:
存儲節點的數據,經過 ID 能夠獲取節點數據,方便節點數據更新。
其次,定義好數據結構之後,就是渲染頁面了,將上面的兩個數據合併組成樹形結構,而後遞歸遍歷建立組件對象。
建立組件的時候,須要獲取對應的組件類型,好比導航組件,輪播圖組件,因此須要一個組件的類型映射表,根據組件的 Type 獲取對應的類型,建立實例。
還有組件的佈局能力,佈局功能抽到容器裏,因此組件在建立的時候會包裹對應的容器,組件的定位由容器負責,不一樣的容器提供不一樣的功能,容器由高階組件提供。
以下圖所示:
圖中 typeFactory 負責組件的建立,建立組件的同時包裹對應的高階組件,
這裏是組件在編輯狀態的渲染過程,發佈之後,考慮的渲染的性能,預先建立了組件的樹形結構。
最後,實現拖拽佈局,佈局徹底是容器來負責,拖拽過程的位置檢測由容器來實現,經過鼠標位置肯定組件的安放位置,修改描述組件關係的數據,觸發從新渲染。
流式佈局演示:
自由佈局演示:
組件屬性編輯
前面說了組件的佈局,除了佈局,還要對組件的屬性進行編輯,編輯也是經過容器來實現的,經過高階組件來複用。
組件也須要遵照一個規範,方便獲取組件的屬性列表,爲組件增長額外的靜態屬性來講明組件的屬性說明。
系統提供了組件屬性編輯器,同時能夠支持擴展出其餘自定義編輯器。同構直出
由於定製頁是須要 SEO 的,因此要作服務器端渲染,也就是要作同構直出。
作同構直出須要考慮如下內容:
Store 中存儲了組件樹和組件屬性數據,直出的不只僅是 HTML,還包括對應的 CSS,這裏使用 css in js 方案 Glamor,渲染 HTML 的同時,也能夠提取對應的 CSS。
下面是同構直出的大體流程:
同構直出的渲染結果:
爲了減少首次渲染頁面的體積,並無把狀態數據內嵌到頁面裏,而是提供了一個狀態的的請求連接,異步加載狀態數據。
一階段完成之後,開始上線運行支持業務,目前已經支持 100+ 的定製頁項目,經過在線編輯、修改、發佈,節約了大部分編碼、構建、發佈的時間,開發效率大幅提高。
因爲一階段是內置的組件庫,包括通用組件以及定製頁業務相關的組件,二階段但願能實現組件可擴展,提高平臺的應用範圍,實現頁面級的組件,加強易用性。
組件市場
組件市場是一個組件的集合,提供可選的組件,組件的粒度能夠開發者控制,能夠是組件級,也能夠是頁面級,能夠內嵌業務,或者是通用的組件。
組件開發CLI工具
提供組件開發腳手架,本地開發、調試環境,能夠發佈組件到組件市場。
組件動態加載
爲了動態加載組件,咱們開發了模塊加載器 BondJs,能夠動態加載頁面依賴的全部組件,將組件註冊到系統裏。
目前組件市場還處於完善階段,計劃年末上線,磨合一段時間,後期但願能夠積累更多的模板,接入其餘業務,能提高運營類項目的效率。
關於第二階段的後續有機會能夠再詳細說明,這裏不展開了。
目前平臺是給內部開發者使用,由於編輯自由度高,須要有必定的前端基礎,系統也提供了模板功能,直接從模板編輯相對易用一些,不過,還是對頁面內元素的編輯,對運營/產品/企業用戶來講仍是有必定的難度。
對普通用戶來講,最容易懂的模型不是頁面的元素,而是業務模型,好比用戶信息、企業信息、職位信息這一類更貼近用戶的模型,因此後期組內同窗和後端同窗一塊兒開發基於後端模板的解決方案,這個方案的優勢是能夠利用企業招聘方的數據模型,好比企業介紹、職位列表等數據,再提供多個後端預置模板,企業只須要維護本身的信息,而後選擇一個模板便可,能夠知足對定製頁要求不那麼高的用戶。
靈活性和易用性是須要平衡的,越靈活每每易用性比較差,通常是經過預約義來講提高易用性,細粒度的組件很靈活,可是易用性差,後續能夠開發內嵌業務的頁面級組件,來提高易用性。
目前,整個編輯平臺已經支持了 100+ 的項目,針對複雜度不高的項目能夠很大提高開發效率,整個項目由於是 Side Project ,一邊支持業務一邊開發,因此花了很多時間,回過頭來看,作這類項目,首先要有明確的目標和受衆,是爲開發者賦能,仍是服務普通用戶,可視化佈局也不是銀彈,因此要想好真正影響效率的地方。好比有些項目開發快,可是面對用戶的頻繁修改需求,效率也很難提高,反過來要控制用戶的需求變動,若是客戶要求不高,直接給個默認模板就能夠,或者提供多樣的選擇,讓用戶選擇相對滿意的模板便可。
後期組件市場上線,但願能夠接入不一樣的業務線,提供更多面向業務的組件或者頁面模板,提高系統的應用廣度,提高運營類項目的開發效率。