CSS模組化(五) CSS的設計模式原則之一:聚合/組合原則
5. CSS的聚合/組合原則--掛多個class還是新建
CSS裡也包含了設計模式的6大原則,今天講講聚合/組合原則--多用組合,少用繼承
假設有如圖3-1所示的模組。
圖3-1 三個簡單模組
我們如何設定它的CSS呢?方案一如程式碼清單3-11所示。
方案一可以實現我們想要的效果,但它非常冗餘,“.numberList1”、“.numberList2”和“.numberList3”的CSS設定相同,“.numberList1 li”、“.numberList2 li”和“.numberList3 li”有部分CSS一致。我們對它們進行改進,產生方案二,如程式碼清單3-12所示。
程式碼清單3-12
除了方案二,還有另一種思路,方案三如程式碼清單3-13所示。
程式碼清單3-13 方案三
方案一將圖中的三個模組視為完全不同且彼此獨立的三個類,分別命名為numberList1、numberList2和numberList3,並對它們分別設定樣式。其缺點是程式碼冗餘。方案二和方案一思路相同,仍將模組視為完全不同且彼此獨立的三個類,只是使用CSS技巧將三個類相同的部分提取出來,去除了程式碼的冗餘。方案三換了種思路,提取了更多粒度更小的類,通過類的組合實現設計圖的效果。
方案二和方案三看似都是不錯的解決方案,其中方案二的優勢是呼叫簡單,一個模組只需掛一個類;方案三呼叫稍麻煩,但也有效控制了冗餘,程式碼精簡。看起來似乎方案二和方案三都不錯,但如果想實現如圖3-11
按照方案二的思路,程式碼如程式碼清單3-14所示。
按照方案三的思路,程式碼如清單3-15所示。
按照方案二的思路,我們需要再定義一個新的類numberList4,在CSS裡需要修改好幾處;按照方案三的思路,我們無需擴充套件新的類,只需在HTML標籤的class裡將之前定義的類重新組合即可。
在面向物件程式設計裡,有類似的情況;繼承與組合。繼承的思路是將一個複雜且包含變化的類,拆分成幾個複雜但穩定的子類。首先明確一個抽象的父類,父類有著幾乎所有的方法和屬性,子類繼承自父類,根據需求,新增新的方法和屬性,覆蓋掉與父類有變化的方法和屬性。但使用繼承的話,任何一點小的變化也需要重新定義一個類,很容易引起類的爆炸式增長,產生一大堆有著細微不同的子類。組合的思路是將一個複雜的類分成容易產生變化的部分和相對穩定的部分,將容易變化的部分拆分出去,每一種可能的變化設計成一個個單獨的類,相對穩定的部分設計成一個主體類。這樣,將一個複雜的類拆分成幾個簡單的類,類之間沒有繼承關係,這遵循了面向物件設計的“單一職責”原則。這些容易變化的類的例項賦值給主體類作為一個屬性,實現了類的組合。用組合的方式,可以大大減少類的數量。在面向物件程式設計裡,有個很重要的原則就是“多用組合,少用繼承”。一些偏激的工程師甚至認為繼承是錯誤的,是造成維護性差的罪魁禍首,主張完全使用組合,拒接使用繼承。
方案三就是借鑑了程式設計領域類的組合的思想,將方案二中複雜的numberList1類、numberList2類和numberList3類拆分成了幾個相對簡單的類,其中相對穩定的部分拆分成numberList類,而可能變化的部分拆分成fl2類、fl6類和red類。通過類的組合,很容易實現類的擴充套件,避免產生類爆炸。
HTML標籤的class屬性和id屬性不同,id只能掛一個,而class可以掛多個,用空格分隔。例如“<p id=’test’></p><div class=”fl2 red box”></div>”。HTML的class與程式中“類”有相同的“味道”,class可以掛多個,從技術上支援了“組合”的用法。我們在使用css時,如果能靈活運用這點就可以大大減少類的數量,一方面減少了程式碼量,提高了可維護性,另一方面使類的職責更單一,彈性更強,增加了類的重用性,提高了開發效率。
掛多個class會不會讓HTML標籤看起來過於臃腫呢?這樣做真的好嗎?臃腫固然不好看,但它帶來的好處卻是不容忽視的,筆者推薦掛多個class,哪怕它讓HTML標籤看起來不太輕盈。Yahoo的YUI3官方演示文件中的一部分程式碼如程式碼清單3-16所示。
程式碼清單3-16 YUI3中的class
可以看出Yahoo的前端開發工程師也喜歡掛多個class的方式。