最近半忙不忙的寫了一個外包網站,網站主要功能是藝術品競拍和藝術衍生品的銷售。工程已經完成了80%左右,現在前後端代碼量已經50W行左右,我主要負責的是前端設計和前端布局。下面就先放一個網站的設計圖吧,因為涉及到甲方的“商業機密”,所以打一下馬賽克:
這篇文章主要算是我對於這個項目的總結或者說是對於這階段自己看的一些前端書或者經驗的一個總結吧,所以設計圖就不貼那麼多了。整個項目的設計圖由最開始的ui定了個首頁稿基調,剩下的介面大部分都是我在首頁稿基礎上做出來的,以後有機會再嘮。PS:不過話說部落格園裡現在遍園子都是.net的文章,前端的文章除了js的,就是那些“可複製可粘貼”的源碼文,希望以後能看到更多前端好文吧。
整個網站的單介面(不包括後端)已經有3,40個了,css檔案累積下來也有10多個(這個之後會細說,這塊兒是我這個項目中做的最失敗的一部分,也是我寫這個blog的原因)。
一個一個問題的嘮,我就說說自己的理解,不太對的地方歡迎交流:
一、什麼是css的架構?為什麼要做架構?
如果做的是一個小的部落格網站或者說是一個小的CMS,那可能很多時候不用考慮css的架構,因為css檔案很少,總共就不到10個介面,給每個介面單獨寫樣式、單獨封一個css檔案也沒有太大的工程量。但是,如果換到這種介面數達到幾十個或者幾百個的大型網站中,css的架構就非常有必要了。而且,好的架構能夠協助團隊共同開發,不可能說總共幾十個介面,3個前端,一人分十幾個,好,你們去寫吧,這樣的工作效率太低,而且極易導致樣式衝突和樣式被覆蓋,可能寫起來很快,每個人都很勤勞的把自己的代碼寫完了,然後後端總合之後發現樣式全亂了,一改改了好幾天,比寫都慢。
合適的css結構能夠協助開發人員減少代碼量,能夠協助前端Team Dev在共同開發的過程中能夠更好的合作。同時它也能最佳化前端的整體結構,合理的css架構能夠減少css檔案數目和css檔案總大小,降低對伺服器的訪問壓力。
它也能大幅度提高前端代碼的重用度和減少代碼的維護成本。對於那種1個小時想改一次介面的甲方,沒有好的css架構真是要瘋了。比如說你每個頁面都有個標題列,每個頁面都是一個單獨的css,然後突然有一天甲方深井冰一樣說,我想改一下樣式,這時候你只有兩個辦法:1.抱著甲方大腿哭訴求不改2.默默開啟電腦開始一個介面一個介面的改。看到這裡很多有開發經驗的同志們應該都知道說,提取這個標題版塊,寫在統一的css檔案內,每個介面都引用一下,最後想改的話只要去總的那個css檔案裡面改就可以了。這就是最簡單的模組化,不過,模組化的過程中還有很多問題需要注意:1.比如3個介面都有標題列,但是3個介面對於標題列字型顏色的要求各不相同怎麼辦?對於上下margin的要求又不相同怎麼辦?2.突然多了一個介面,它有標題列,但是它標題列裡多了個背景圖片,這個怎麼解決?再麻煩一點,它標題列裡多了一個<p>表簽,多出來的又怎麼布局?這種解決模組之間差異的問題確實值得好好研究一下。
通常的css架構,或者是當前網站的css架構,包括了對瀏覽器預設樣式的覆蓋重設、對網站內部模組的提取抽象化、約定css代碼規範、衝突解決等功能。如果項目中有引用其他的成熟架構,比如說bootstrap、yui,怎麼把這些架構和自己寫的分割開,能實現樣式而又不衝突?稍後慢慢嘮。
怎麼做css架構或者怎麼實現簡單的css結構?
答:寫代碼啊!
二、css的架構從哪裡做起呢?
動手一個項目前,不能看到設計圖就直接幹,應該先想的是怎麼樣去寫。就像我們老師最常對我們說的一樣“只會寫代碼,你只是平庸的程式員。能夠做出好的架構或者能夠安排好項目怎麼開發的,才是高端點兒的程式員。平庸的程式員只能吃香蕉,高端的程式員有時候還能吃點菠蘿、蘋果啥的”。直接動手開始寫,寫著寫著就會發現很多時候自己是在做重複功,不斷地複製粘貼或者是為了一個介面模組重寫一種又一種樣式,或者寫著寫著發現“臥槽,衝突了,樣式亂了”,再或者寫著寫著發現自己寫的不對想回去改,然後開始挨個檔案的改...這種沒有架構的、笨拙的在寫css就是在幹體力活,很久之前寫的一個項目就是這樣,20幾個介面慢慢改去吧,改了整整兩天,都要瘋了...
動手一個項目前,最起碼的,應該想清楚大致有多少個css檔案,哪些css檔案需要先寫出來一個固定版本,哪些css代碼可能會大量重用,哪些css檔案可能會有大規模的改動。然後根據這些css的詳細要求去開始動手寫初版。
比如我上面放的,最直觀的header首部欄:,在每個介面都是一樣的。當然這個我們可以在後端裡面用分布視圖layout來實現,但是在介面前端實現的初期,是不是也應該把這一塊兒的html、css、js抽離出來,這樣在後端進行最後整合的時候也能快一些,而且萬一碰到個聖誕節,客戶說給上面背景色換成藍色吧,這樣直接翻到header.css裡改一改樣式就好了,不用苦逼的去“體力活”了。
所以,第一種css前端架構設計的方式就是:按照地區劃分。
按照頁面內的元素或者模組的地區定位,網站中可以劃分出來很多地區:header、footer、sidebar、slogan等等,針對於這些地區單獨定位能夠有效實現分布視圖的劃分,每個地區都被抽離出來,建立一個介面的時候我們只需要在裡面拼一拼就好了。沒記錯的話,yui就是這麼乾的。
在這個拍賣網站的css裡我沒有單獨抽離出來,因為我覺得單獨抽離成一個header.css、footer.css檔案有點贅餘,css檔案數在增多,而每個檔案內的程式碼數卻很少。這個還要根據具體代碼來看,一個footer樣式寫了幾十行的話,那就抽離成一個檔案吧。所以我在總的css檔案:layout.css裡其實是按照地區進行寫的:。當我想要更改底部導航樣式的時候,直接就去layout.css裡往下翻找,改掉就可以了。
然而我們對介面進行分割之後發現,還是有很多代碼在大量重複出現,比如說登陸框、比如說表格、比如說文字框等等,所以有了第二種劃分方式:按照功能進行劃分。
按照功能劃分就是看元素的介面內功能是什麼,然後根據具體功能,把具有相同功能的元素、模組抽離出來:font、color、button、form等等,這個應該是現在很多成熟架構採用的模式,比如我大bootstrap就是這麼乾的,下面是bootstrap2.3的less檔案夾的,很明顯,都是一個個功能模組,最後我們直接應用的是被全部整合壓縮的.min.css,裡面其實也還是這種結構:
按照功能劃分還是蠻爽的,因為你可以為每個功能劃分添加統一的首碼,在有代碼提示的編譯器裡寫代碼簡直極速。換成那種按地區劃分的話,有時候就略微蛋疼了“哎呀,頁尾的css名是什嗎?哎呀,小王寫的那塊兒側邊欄的類名是什麼”。
在這個項目的代碼裡,我其實採用的是第一種方式和第二種方式混用的模式,從我上一張css檔案就能看出來,我不僅把重複出現的地區模組的代碼抽象了出來,而且也把側邊欄、遮罩這種功能模組給抽象整理了出來,盡量提高My Code的複用度。
之前還覺得自己的這個項目的架構做的不錯,但是後來越寫越坑,因為很多時候自己都是在做無用功。我犯的傻X錯誤:
1.模組抽象有局限。比如說表單有要差一個特殊的元素,原來寫好的模組就沒法用了,又得重頭寫一遍。
2.模組抽象不完全。在我認為自己已經把模組抽象做的差不多的時候就開始全力寫,寫著寫著發現,有的模組被遺忘了,很多模組需要一遍一遍的手寫。
3.css類名不規範說到底是模組沒有劃分好。這個網站寫到現在,我的命名已經詞窮了,它這裡有很多介面:加入購物車、加入收藏列表、查看購物車、確認支付、填寫確認訂單、一口價支付...沒有好的英文底子真是噩夢...所以只能翻譯漢語名,然後駝峰命名法:AddCart。其實命名法還有很多,駝峰命名法最大的好處就是可以很直觀的命名,不用考慮別的,但是駝峰命名法在子類命名的時候就比較頭疼了,一個又一個的長單詞...另一種命名方法是劃線法,為了避免麻煩直接用的底線沒用中杠add_cart,這種命名法對於子類命名特別爽,這個後幾篇總結的時候再嘮。
------------下面---------就是------------本篇-------核心-----了---
下面就是本篇文章的【核心】了,也是我痛心疾首的反思T^T最近項目受阻、半寫不寫的狀態,所以看了一些前端代碼規範、網站前端開發的總結的書,然後發現了一種新的結構方法,看完之後真是整個人都不好了。推薦這本書《編寫高品質代碼-web前端開發修鍊之道》
另一種比較推薦的css架構方法是:按照介面職能進行劃分:這裡將網站的整個前端抽象成了一個軟體或者是一個項目,這時候我們要考慮的就是項目底層是什麼,項目的表現層是什麼,類似於大家常說的mvc的思想,把前端架構也進行mvc般的劃分,可以把所有的css檔案歸納為三類:
1.base類 2.common類 3.page類
這三類並不是像地區架構、功能架構中並列作用的模式,而是以base類為底層,逐層影響,層疊作用,大概畫了個作用圖:
確實,就像這種金字塔結構,下面詳細介紹一下每個類的作用。
[1.base類]
顧名思義,基礎,它是整個css架構中最基礎的部分。它負責提供瀏覽器預設樣式重設、基礎功能實現。說到base裡的基礎功能實現,它主要指的是那種涉及範圍極小、抽象程度高的原子層級的功能類實現。比如我們最常見的.f12{font-size:12px;},.mt30{margin-top:30px;},每一個原子類只負責實現一種功能,絕對不涉及到具體的頁面ui,只是為上幾層提供原子功能,具體某模組的實現則有這些原子類間進行組合實現。當然,base類還要負責瀏覽器預設樣式的reset,這個我覺得yui實現的就很靠譜,現在很多網站的<h123456>都是不加粗的,這個都需要提前在reset部分寫好。
base類是整個css架構的地基,所有介面都會引用整個檔案,這對這個檔案提出了要求:1.檔案大小不能過大 2.檔案可靠性要高,不能出現多個版本 3.寫成之後盡量減少維護次數或者盡量不用維護。而且不同網站的base類可以共用,因為base類不涉及任何具體的ui樣式,高度可移植。
具體base類檔案都有什麼,這個下一講來好好嘮嘮,今天沒空了。
[2.common類]
普通類,它是利用css基礎類實現的基礎模組的css檔案,我們已經把整個介面裡的文字、邊距、顏色等原子工程抽離出來了,現在需要我們為當前網站定製模組了。
設計原則裡“統一性原則”要求到同一網站必須保持風格一致,你不可能首頁扁平化,進了列表頁就來個高光高陰影還帶酷炫flash的web2.0風格頁。所以,同一網站內的搜尋方塊、文字框、按鈕、列表大多數情況下都是統一風格的,所以這就給我們個機會,把這些會重複出現的模組抽離到common類裡,類似於MVC裡面的model,也類似於我們上面講述的架構功能劃分的具體功能檔案。為了盡量保證可重用和靈活使用,我們需要對這些模組進行完整封裝。
話說,模組需要進行訂製時怎麼辦?
我想到了兩個辦法,一種是利用less等語言給模組預留樣式介面,直接修改設定檔,再動態輸出css檔案。2.盡量減少模組的ui屬性,比如bgcolor或者是border,可以空缺,而在實際使用時根據自己的需要與原子類進行組合。但是這種方法可能會對原子類有要求而且會對base檔案產生影響,所以我自己又編出了個詞:分子類,顯而易見就是提供針對於模組的大原子類定製,為每一個模組定製專屬樣式類,同樣至於common層,需要定製模組樣式時只需要彼此組合即可。之後的文章裡寫點東西示範一下。
[3.page類]
頁面類,從圖裡也能看出來,它在金字塔的塔尖,而它的作用範圍也是最小的,就是每一個頁面,到不至於每一個頁面一個css,但是也差不多吧。 page類就是負責提供頁面級樣式的。page類css可能產生一些比較令人糾結的問題:1.page太多,所以page css單檔案太多,每一個檔案就是一個http請求,伺服器能受得了不?2.page css為了不多,所以合并在一個page.css裡,但是命名怎麼辦?比如.part, .one, .main, .theme....這些頻繁出現的類名合并衝突怎麼辦?
第二個問題可以通過命名範圍限定來解決。
至於第一個問題,你可以把css單檔案合并,然後你就去看第二個問題的答案吧。
總結下來,在開發中,base和common類一般由一個人完成,在他完成這些類之後其他人接手項目,開始添些page.css,所以page層裡代碼奇多,如果應用到分布視圖,一個整頁面其實是由若干個小介面拼起來的,那麼如何避免衝突?如何避免樣式覆蓋?以後詳談。
_(:з」∠)_碼了這麼多字累死我了,今天就先寫到這。下篇見~~【求交流求師傅帶求內推求不吐槽...】
下一篇文章,咱們詳細談談base類css檔案,以及我自己對項目css的重構。
最後,最後,我想說的就是↓↓↓