背景與現(xiàn)狀
(一)背景
“不要寫死”——程序開發(fā)過程中經(jīng)常提到的一個問題。我們運用各種設(shè)計模式進行抽象、封裝,就是為了讓我們的代碼看起來不是那么“死”,從而能夠靈活的適應(yīng)各種“變化”。
如今互聯(lián)網(wǎng)的變化,可以說世界的變化超出每一個人的預(yù)測,那么對于快速變化的市場與用戶需求,尤其我們客戶多樣,存在或多或少的個性化定制需求,我們需要更加快速、高效地做出響應(yīng)——頁面可配置的概念應(yīng)運而生,其包括UI(界面與交互)、業(yè)務(wù)、數(shù)據(jù)、配置等諸多方面。
頁面的自定義比作蓋樓,添加一個樓層,每層可以自定義內(nèi)容,譬如商品、優(yōu)惠券、商品排名等。在淘寶旗下的店鋪裝修平臺——“淘寶旺鋪“中,淘寶店家可以選擇基礎(chǔ)模塊的內(nèi)容,編輯首頁或新建頁面,動態(tài)配置頁面。

淘寶旺鋪裝修App

淘寶旺鋪裝修PC
這種頁面配置有以下特點:
- 靜態(tài)數(shù)據(jù)或后臺數(shù)據(jù)
- 單頁(多圖、圖文混合偏多)
- 頁面區(qū)塊耦合度小,可靈活拼裝
- 新建的頁面可以快速發(fā)布上線
(二)現(xiàn)狀
目前系統(tǒng)各業(yè)務(wù)模塊業(yè)務(wù)耦合度較高,依賴較強,沒有統(tǒng)一的配置管理方案與渲染實現(xiàn),重復(fù)造輪子。
(三)設(shè)計思考
- 不能因為技術(shù)架構(gòu)上對頁面可配置支持的引入,帶來新的開發(fā)成本和負擔;
- 引入可配置支持的頁面應(yīng)該與引入前基本保持在同樣的性能表現(xiàn),不能因為頁面可配置明顯拖慢業(yè)務(wù)性能。
所以,在實現(xiàn)頁面可配置的前提下還有兩個目標:對業(yè)務(wù)無侵入、高性能。
核心分析
(一)核心問題
可配置頁面,要解決三個核心問題:
- 頁面布局和樣式
- 頁面內(nèi)容,即數(shù)據(jù)
- 頁面的交互
(二)頁面分析

頭條號創(chuàng)作者首頁
上圖是我截取的頭條號創(chuàng)作者首頁的圖片,我把它劃分成了不同的區(qū)塊,并且標上了編號。整個頁面,我們將它稱為畫布(Canvas,或者叫做頁面),里面一個個帶有編號的紅框,稱之為容器(Container)。實際上,畫布(頁面)也可以理解為是一個足夠大的容器,也是頂級容器,便于理解,暫時稱它為根容器(Root Container)。
現(xiàn)在我們來具體分析一下這個頁面:
- 整個詳情頁面被認為是一個完整的畫布(白紙),由不同(大小不一)的容器構(gòu)成,這些容器就像樂高積木,可以用它組裝搭建成不同的頁面;
- 容器由各種組件(Component)填充,組件包含數(shù)據(jù)源、顯示樣式、交互邏輯等一套完整的屬性(Attribute);
- 組件中包含banner、按鈕等單元,這類最小的組件單元,我們稱為元素(Element),這一類元素邏輯上將無法再被拆分;
- 原則上容器可以由更小的容器構(gòu)成,它們是遞歸構(gòu)建的,呈樹形結(jié)構(gòu),這是一個迭代實現(xiàn)的過程,本次設(shè)計暫時不考慮嵌套。
綜上分析,我們可以得出五個概念:
- 畫布(Canvas):整個頁面,可以理解為一張白紙;
- 容器(Container):整個畫布可以被拆分成不同的區(qū)域(Region),每一個區(qū)域稱之為容器。在這次設(shè)計方案里面,暫時不考慮容器嵌套更小容器的問題;
- 組件(Component):組件是粗粒度的,包含部分頁面的UI、數(shù)據(jù)以及與之相關(guān)的業(yè)務(wù)邏輯,容器由可以由若干個組件構(gòu)成,組件填充容器的顯示內(nèi)容(其實組件也可以稱為模塊,之所以稱為組件是為了后續(xù)豐富通用組件庫考慮);
- 屬性(Attribute):單個組件包含數(shù)據(jù)源、樣式、交互邏輯等一套完整的屬性;
- 元素(Element):組件包含若干頁面元素(banner、button、tab、label等),它們是邏輯上最細粒度的單元,不可再被拆分,本期設(shè)計不細化到元素層面。
(三)頁面布局
有了以上概念定義,我們再回過頭看這個頁面。從布局層面來看,它就是一個網(wǎng)格布局,以從上到下,從左到右的順序逐個分布容器與組件,但是就這個頁面來說,它還不是簡單的橫向縱向網(wǎng)格。

網(wǎng)格化布局
我們將前面頭條號創(chuàng)作者首頁的內(nèi)容去掉,只留下布局,那么就是上圖中這個樣子,為了簡化邏輯,我們把容器都設(shè)計成流式布局,所有組件一個個自左往右,自上而下堆疊排列。
(四)頁面內(nèi)容——組件
每一個組件都有自己獨立的邏輯和UI,組件之間完全解耦,這樣就可以很方便地通過排列模塊來完成不同的頁面定制化需求,使一個頁面可以展示不同的內(nèi)容。原則上,組件并不依賴某一具體頁面,組件也可以在不同的頁面之間進行復(fù)用。
- 組件采用聲明式編寫,本質(zhì)是一個json對象,封裝由具體的框架去實現(xiàn)
- 由于聲明式的組件是一個json對象,當擴展組件功能或者改變組件行為時,可以通過覆寫json對象的方式實現(xiàn),最后交由框架封裝
(五)頁面交互
- 傳統(tǒng)頁面元素事件:點擊、移入、移出、彈框、跳轉(zhuǎn)頁面等
- 業(yè)務(wù)事件:提交前、提交后、數(shù)據(jù)后處理等
問題與思考
(一)布局復(fù)雜
頁面布局不一定是網(wǎng)格化有序排列,布局樣式多元,那么容器層面怎么支持與兼容是需要面臨的問題
(二)組件復(fù)雜
業(yè)務(wù)組件復(fù)雜,組件入?yún)⑿问蕉鄻樱尤敕绞饺绾谓y(tǒng)一
(三)交互復(fù)雜
彈窗、跳轉(zhuǎn)、校驗、提示,各種前端交互紛雜多樣
(四)業(yè)務(wù)需求迭代
- 隨著業(yè)務(wù)需求不斷迭代,組件如何適應(yīng)變化
- 組件的狀態(tài)數(shù)據(jù)和函數(shù)方法可以通過上述方法覆寫,但是視圖模板的變動如何支持?
- 組件必須遵照容器布局系統(tǒng)規(guī)則暴露一些特定的屬性和方法,便于注入一些數(shù)據(jù)源對象,便于容器布局系統(tǒng)統(tǒng)一管理組件
- 畫布定義好以后,在拖動組件到畫布中編輯時,是否能修改畫布布局? 如果能修改,技術(shù)復(fù)雜度是否可控?
(五)其他思考
- 布局配置、渲染獨立,不與業(yè)務(wù)系統(tǒng)耦合,制定組件接入規(guī)范;
- 每個組件需要獨立打包,組件內(nèi)容牽涉業(yè)務(wù)數(shù)據(jù)調(diào)用、公共組件的調(diào)用封裝問題;
- 單個組件樣式、業(yè)務(wù)相關(guān)數(shù)據(jù)與邏輯獨立管理,組件之間互不影響。
規(guī)劃與步驟
- 功能:把組件庫做得更豐富,盡量提供更多的基礎(chǔ)組件
- 易用性:擴展組件自定義功能,支持更多的屬性配置
- 落地:適應(yīng)新需求和變化