設計公共元件需要注意什麼
本文源於我們近期抽取的 ListFrame[參考中有介紹] 公共元件,以及後續使用和維護這個公共元件的思考 。
抽取一個公共元件,至少應當仔細考慮一下4點:
1、公共元件不應該整合定製性強的功能,可以整合通用或較固定的功能,但應預設關閉那些不常用的功能
到目前使用了 ListFrame 的列表有9個(列表共19個,3個未完成,7個尚未使用公共元件)。
這些列表的搜尋條件總共約有12種,但是listFrame只封裝了6個,且這6個 只有一個預設是開啟的。
為什麼不封裝另外6個?其的5個只有少數列表用到,封裝他們 增加了公共元件的程式碼量,但又沒有很高的利用率。
還有一個也就是類別搜尋,幾乎所有的列表都有這個搜尋條件,但不同種類的內容類別完全不同——這是定製性很強的功能(文章型別的類別,遊戲型別的類別 完全不同)!
(公共元件不能保持穩定的,就是失敗的)
這有點小兒科了吧!
實際上識別出哪些功能是通用的(應該封裝的),哪些是常用的(應該預設開啟的),並不是拍腦袋決定的,是在使用公共元件的過程中,不斷修正總結得出的。
維護公共元件,你一定要有一顆開放的心態。元件好不好,由使用的情況說了算,敢於承認失敗,才能不斷改進。
2、引數的配置要簡單且靈活
如果你想讓你的元件功能強大,通過一些配置就能快速擴充套件,那麼一定要避免將配置設計的過於複雜。
配置很複雜的話,別人為什麼要用?這無異於將寫原始碼的工作量 轉移到了寫配置上,沒有任何好處,反而讓程式碼更難理解(額外的要先理解你的公共元件)。
將配置設計的簡單關鍵就是:用好預設值和型別過載
構建列表框架,你必須要考慮分頁:
有些列表(如展示全部內容的列表)是沒有分頁
分頁有pageNo和pageSize屬性,且初始值是可以設定的,ajax請求時攜帶的引數名最好也是可以配置的
於是可能你的元件應該這樣使用:
<list-frame :showPager="{
show:true, pageNo:{ name:'pageNo', initial:1 }, pageSize:{ name:'pageSize', initial:10 }}"></list-frame>
後臺在設計介面時,通常引數名就是 pageNo 和 pageSize;前端使用場景中基本上初始的pageNo是1,pageSize為10。採用預設值,所有的配置都可以省略:
<list-frame :showPager="{show:true}"></list-frame> <!-- 沒有傳入的欄位,就使用預設值,而非空(做好空值適配很重要) -->
為了更簡單,再加上型別過載。完整設計程式碼如下:
class PagerConfig{ show?:boolean, pageNo?:{ name?:string, initial?:string } pageSize?:{ name?:string, initial?:string } } // 型別過載 showPager:Boolean | PagerConfig // 預設值的定義與使用: const defaultPager = { show: true, pageNo: { name: 'pageNo', initial: 1 }, pageSize: { name: 'pageSize', initial: 10 } }; this.pagerConfig = Object.assign( {}, defaultPager, typeof this.showPager === 'boolean' ? { show: this.showPager } : this.showPager ); // this.pagerConfig 就是最終的配置了!
那麼使用時,就可以這樣寫了
<list-frame :showPager="true"></list-frame> 或: <list-frame show-pager ></list-frame>
現在可以看到,一切變的非常簡單,同時又保持了足夠的靈活性!
3、相關的配置要集中
將相關的配置集中在一起,更利於使用者使用,可讀性更強。
ListFrame 封裝了 批量刪除 和 批量上下架 的功能。為什麼要將這兩個功能封裝呢?因為:
1、有很多業務無關邏輯值得我們去封裝,如disable校驗,刪除和下架時要彈出輸入框,要求使用者輸入刪除原因或下架原因;
2、通用性很強,幾乎所有的列表都有刪除功能,所有已釋出列表都有上下架功能;
3、不同列表除了對應的上下架介面,刪除介面不同外,好像沒有什麼其他不同的。
看看下方程式碼:
如果開啟批量刪除 除了設定 itemsDelAble 為 true,還要提供 delFn 刪除方法;如果開啟批量上下架 除了設定shelfOperateAble 為 true ,還需要提供offshelfFn 和 onshelfFn 兩個方法。
既然提開啟功能和供方法必須同時存在,為什麼不把他們繫結在一起呢?我們將 itemsDelAble 和 shelfOperateAble 有bool型別變成了 object 型別,於是很容易實現了集中配置的目標。
對比一下將配置集中前後的程式碼,是否後者更容易理解,更方便使用了呢?
<!-- 集中配置前: --> <list-frame :getPageFn="getPage" :itemsDelAble="true" :delFn="delFn" :shelfOperateAble="true" :offshelfFn="offshelfFn" :onshelfFn="onshelfFn" ></list-frame> <!-- 集中配置後: --> <list-frame :getPageFn="getPage" :itemsDelAble="{delFn}" :shelfOperateAble="{offshelfFn,onshelfFn}" ></list-frame>
4、避免出現職能交叉的配置
我發現,這一點錯誤,即便是大型UI框架也會犯。我現在開發的專案所採用的UI框架,關於Button就存在這個問題。下面就用個api截圖來說明:(就不發 連結,也不指明是哪個框架了)
按鈕的 type 大部分值都是表示主題顏色的,如default,primary,info等,但 text(文字按鈕) 和 dashed(虛線框按鈕)除外,我覺得這兩個應該是屬於shape(形狀)的值。
這樣的 type 和 shape 職能交叉了。現在要實現一個文字按鈕,有不同顏色 —— 竟然做不到了!
我們在開發 ListFrame 也存在這樣的錯誤,後面使用時發現後才改正的,這裡就不說了,因為上面舉的例子已經能很好的說明這個注意點了。