原文載于 zendev.com。
最近仰税,「CSS in JS」獲得了大量的關(guān)注枉圃。原因很簡單:CSS在運行在公共命名空間中,可能引發(fā)不好的副作用礁凡,導(dǎo)致代碼混成一團(譯注:原文是意大利面式代碼)高氮,給維護代碼庫造成極大的困難。于是人們用JavaScript來解決這個問題顷牌,把所有的代碼(CSS剪芍、JS)封裝進模塊里然后使用諸如Webpack之類的工具將一切縫合起來】呃叮看罪裹!JavaScript也可以處理CSS了,為什么我們不把所有的CSS也放進JavaScript里然后封裝成模塊呢运挫!
有一個真正亟待解決的問題--人們確實可能會寫出可怕的状共,難以維護的,堪稱災(zāi)難級別的CSS滑臊。事實上口芍,這樣的事情非常普遍箍铲。別誤解我雇卷,我喜歡JavaScript……但作為這個問題的解決方案,「CSS in JS」就像是用你最喜愛的錘子換掉你老舊的螺絲刀。當然关划,(用錘子)你可以把螺絲釘更深地釘進墻里小染,但是,當初你用螺絲刀取代指甲擰螺絲時不也消滅了許多困難而富有價值問題嗎贮折?
CSS與JavaScript的關(guān)鍵差異
讓我們看看CSS專注解決的問題與Javascript專注解決的問題之間有哪些關(guān)鍵性的差異吧裤翩。
結(jié)構(gòu)化/行為化 Vs 圖形化
支持「CSS in JS」的一個常見論據(jù)是“我們過去認為分離關(guān)注點很重要,但是看看JSX调榄!”踊赠。這個論據(jù)用這個(其本身也充滿爭議)的例子來論證清晰地分離關(guān)注點是錯誤的,將CSS寫入JS內(nèi)也同樣可以提升生產(chǎn)力每庆。
這個觀點忽略了結(jié)構(gòu)化/行為化屬性與圖形化屬性之間的差異筐带。當關(guān)注點之間事實上是分離的時候,分離關(guān)注點是確實有價值缤灵。我從兩個方面解釋伦籍,JSX提升了生產(chǎn)力的原因是結(jié)構(gòu)和行為是緊密相關(guān)的--大量的Javascript邏輯必須操作HTML結(jié)構(gòu)實現(xiàn),所以分離兩者只會增加理解難度腮出,而非減少帖鸦。
對比很大程度上是由CSS實現(xiàn)的圖形化屬性。CSS與HTML并非緊緊聯(lián)合而是松散的組合--這也是為什么人們可以直接給出一個產(chǎn)品所有功能的線框圖而不需要附加很多樣式胚嘲。把你的CSS放入你的邏輯代碼里是一種不必要的耦合作儿,只會增加理解難度。
松耦合 Vs 緊耦合
耦合的概念為我們做出權(quán)衡提供了另一個思考角度馋劈。人們廣泛認可:設(shè)計松耦合的系統(tǒng)可以提供更好的擴展性立倍、可維護性和可閱讀性。樣式僅僅和HTML結(jié)構(gòu)有松耦合--視覺上非常相近的UI元素可能在底層結(jié)構(gòu)侣滩、邏輯甚至行為表現(xiàn)上有著顯著的不同口注。相對的,交互元素的交互邏輯必定緊緊依賴操作HTML結(jié)構(gòu)君珠。
「CSS in JS」造成的新問題
視覺一致性
另一個Javascript的邏輯結(jié)構(gòu)性質(zhì)與CSS的圖形/視覺性質(zhì)之間關(guān)鍵的不同是:對于一致性的需求寝志。在Javascript的世界里,如果你能把每一個組件做的更獨立一點策添,那么代碼質(zhì)量更高材部。如果適當?shù)姆庋b代碼,你甚至可以把每一段Javascript代碼片段獨立處理唯竹,而不需要關(guān)注他們相互之間內(nèi)部的一致性乐导。
與你的視覺輸出相比較--如果每一個組件都是與其他組件完全獨立的視覺呈現(xiàn),你的網(wǎng)站或者應(yīng)用將呈現(xiàn)災(zāi)難性的混亂浸颓。當然物臂,每一個組件都有其獨有的屬性旺拉,并且這些屬性之間應(yīng)該相互獨立以防泄漏污染彼此,但對你的站點而言棵磷,視覺的一致性是一項非常重要的需求蛾狗。這也是使用CSS樣式表的核心原因之一,一個難以理解的仪媒、失控的樣式表可以說是一場災(zāi)難沉桌,而恰當?shù)厥褂肅SS,它則會是一個非常有力的工具算吩。
代碼重用
在軟件開放領(lǐng)域留凭,保證事情‘DRY’(Don‘t repeating yourself,意為不要讓自己重復(fù)做已經(jīng)做過的事)并且寫出可復(fù)用的代碼通常被認為是一種非常好的練習偎巢。它可以使得我們每次只需要修復(fù)與更新一個地方而不是在整個代碼庫內(nèi)大量重復(fù)的地方冰抢。
使我困惑的是,「CSS in JS」提倡這個觀念(DRY)是必要的艘狭,但書寫樣式時又采用“復(fù)制&粘貼”的方法挎扰。如上文提到的,在你的網(wǎng)站或應(yīng)用內(nèi)保證各種元素的視覺一致性是極其重要的巢音。這意味著如果每一個組件只需要對自己的樣式負責遵倦,最終你會制造數(shù)量龐大的重復(fù)。當你的品牌決定更換它的設(shè)計語言時會發(fā)生什么呢官撼?如果你想要引入一個新的主題梧躺,甚至只是隱隱地改變你的應(yīng)用的界面以跟上現(xiàn)代設(shè)計的實踐。你將不得不深入到每一個組件去實現(xiàn)這些改動傲绣。從可維護性角度看掠哥,這種方案造成了可維護性的噩夢。
真正的解決之道:更好的CSS實踐
希望到了這里秃诵,我已經(jīng)說服了你相信「CSS in JS」是一個糟糕的策略续搀,但仍然有一個真正的問題需要解決。這個概念會被提出正是因為過去有著數(shù)量龐大的菠净,可怕的禁舷,難以的維護的CSS樣式表。 “只添加CSS”和盤根錯節(jié)的樣式表會導(dǎo)致每一個改動都充滿了風險毅往,這在生產(chǎn)中令人無法控制牵咙。我曾經(jīng)也陷入過這樣可怕的境地里。但幸運的是攀唯,已經(jīng)有成千上萬聰明的人在思考并解決這個問題洁桌。真正的解決之道并不是提供一個Javascript之錘然后引發(fā)另一個問題,而是要意識到:精巧地構(gòu)建CSS是一件真正的工程侯嘀,一項與寫Javascript有著截然不同的系統(tǒng)方法和需求的工程另凌。而且創(chuàng)建簡單有效谱轨,可維護,可擴展的樣式表已經(jīng)有了可供參考的最佳實踐途茫。
如果你在這個領(lǐng)域還是萌新碟嘴,你可以參考以下實踐方案:OOCSS, SMACSS, BEM, ITCSS, 和 ECSS. 其中每一個方案的背后都有著大量的思考溪食,但和每一個工程問題一樣囊卜,世上并沒有“完美的解決之道”,只有不同的權(quán)衡方案错沃。采用其中任何一種實踐方案都可以提升你的CSS技巧栅组,助你擺脫樣式表的地獄。關(guān)鍵在于承認這是一門工程學科枢析,理應(yīng)獲得其他工程學科同等的關(guān)注和嚴謹對待玉掸。
P.S.?—?If you’re interested in these types of topics, I send out a weekly newsletter called the ‘Friday Frontend’. Every Friday I send out 15 links to the best articles, tutorials, and announcements in CSS/SCSS, JavaScript, and assorted other awesome Front-end News. Sign up here: https://zendev.com/friday-frontend.html
原載于 zendev.com 2017-9-11。
譯者按:
作者的觀點我有相當一部分的贊同醒叁,所以才選擇翻譯了這篇司浪。雖然9月的文章現(xiàn)在看似乎有點過時了,但一些問題是始終存在的把沼。純粹的分割每一個組件并在JS中書寫CSS會造成很大的割裂“∫祝現(xiàn)在React方向已經(jīng)有了一些更有機的方案比如CSS in module。仍然書寫CSS文件饮睬,并通過一些方式實現(xiàn)樣式的服用租谈,又兼具了CSS in JS的書寫特性。但在實踐上捆愁,仍有一些道路要走割去,一些開發(fā)仍然會完全獨立所有組件,將一些重復(fù)的樣式寫的到處都是昼丑,非成肽妫可怕。前端方面目前的問題就是更迭太快菩帝,開發(fā)者疲于追逐新的技術(shù)页慷,甚至一個技術(shù)還沒有很好的實踐下去,又開始使用新的技術(shù)胁附。最終技術(shù)雖然在更迭酒繁,代碼的質(zhì)量依然是一樣的缺乏可維護性,可擴展性控妻。無論使用什么技術(shù)州袒,深入思考最佳實踐方案,才是進步之道弓候,盲目追逐新穎的框架與技術(shù)郎哭,可能只是囫圇吞棗他匪,最終什么營養(yǎng)也沒有吸收進去。