這是未來(lái)的趨勢(shì)所向盹牧,如是我行。
注意:原文發(fā)表于 2017-9-6沈撞,隨著框架不斷演進(jìn)慷荔,部分內(nèi)容可能已不適用。
CSS 日漸惹人憎惡缠俺。
究其原因頗多显晶,歸根結(jié)底,皆因 CSS 給人的感覺總是飄渺迷蒙壹士、變幻莫測(cè)磷雇。
譬如微調(diào)某個(gè)樣式后,卻出乎意料地殃及一些看似毫無(wú)瓜葛的布局躏救,尤其是準(zhǔn)備部署之時(shí)唯笙。
這類經(jīng)驗(yàn)如果你從未體會(huì)過(guò)的話螟蒸,你要么是不明就里的新手,要么是登峰造極的高人崩掘。
故此 JavaScript 社區(qū)又開始擼起袖子著手炮制七嫌,只消數(shù)載,各色各樣的 CSS 庫(kù)宛如雨后春筍不斷涌現(xiàn)苞慢,它們統(tǒng)稱為 CSS-in-JS诵原。
然而 CSS 最棘手的問(wèn)題也許并不需要 CSS-in-JS 亦可解決,對(duì)此你可能還不知情挽放。
倘若果真如此绍赛,那么編寫 CSS 將是一種愜意的享受,而非痛苦的忍受辑畦,此外吗蚌,CSS-in-JS 也會(huì)產(chǎn)生新的問(wèn)題要去解決,未免有點(diǎn)旁生枝節(jié)航闺。
本文并非要和 CSS-in-JS 針鋒相對(duì)褪测,也不否定社區(qū)所做的努力猴誊,它在 JS 生態(tài)中如此活躍潦刃,且每周都有新的想法出現(xiàn)。
其實(shí)我目的是想介紹一種讓人更加愉快的替代方案 —— 它就是帶有真正 CSS 的單文件組件懈叹!
CSS 最大的問(wèn)題
CSS 中的一切都是全局的乖杠,正因如此,為某個(gè)標(biāo)記上編寫的樣式澄成,可能會(huì)使另一個(gè)標(biāo)記受到牽連胧洒。
也正因如此,開發(fā)者經(jīng)常借助于各種命名空間的約定(而非“規(guī)則”墨状,因?yàn)殡y以實(shí)施)卫漫,但此法只會(huì)徒增 RSI 的風(fēng)險(xiǎn)。
如果你置身于團(tuán)隊(duì)之中肾砂,情況愈加惡劣列赎。他人所寫的樣式無(wú)人敢改,通常無(wú)法猜測(cè)它們是做什么用的镐确,應(yīng)用在哪些標(biāo)記了包吝,以及如果刪掉會(huì)帶來(lái)什么災(zāi)難。
其結(jié)果是:樣式表必須只增不減源葫。
你無(wú)法得知哪些代碼可以安全地刪除诗越。因此常見的做法是用一些更具體的樣式來(lái)覆蓋現(xiàn)有樣式,哪怕是在相對(duì)較小的項(xiàng)目上亦是如此息堂。
單文件組件扭轉(zhuǎn)乾坤
SFC 背后的思想十分簡(jiǎn)單:在一份 HTML 文件中編寫組件嚷狞,該文件可以包含描述組件樣式的 <style>
和描述行為的 <script>
標(biāo)記。
Svelte、Ractive床未、Vue 以及 Polymer 都是遵循這種模式褂乍。
(顯然我們?cè)谖恼缕溆鄡?nèi)容都將使用 Svelte,但是如果使用模板會(huì)讓你膽戰(zhàn)心驚的話即硼,其實(shí)你的擔(dān)心是多余的逃片,不過(guò)這又是另一個(gè)話題了,那你可以使用 Vue只酥,它允許你在 SFC 中編寫 JSX)
如果你從未接觸過(guò) Svelte褥实,不妨先參看這篇文章:無(wú)招勝有招:為何我們沒有及早悟到這個(gè)辦法?裂允,或者看看用戶的評(píng)價(jià)损离。
應(yīng)用這種模式,結(jié)果會(huì)發(fā)生幾件美妙的事情:
組件的樣式都是局部樣式(scoped)绝编,不會(huì)向外泄露僻澎,沒有不可預(yù)知的級(jí)聯(lián)情況,徹底擺脫為了防止名稱沖突而硬取的超級(jí)啰嗦的類名十饥。
你無(wú)需再去文件夾中苦苦追查那些破壞你樣式的規(guī)則窟勃。
編譯器(例如 Svelte)能夠識(shí)別和刪除無(wú)效的樣式,從此不再是“只增不減”了逗堵!
下面我們來(lái)試試探明究竟秉氧。
所有代碼編輯器都能識(shí)別這些 CSS,其內(nèi)置了自動(dòng)完成蜒秤、監(jiān)測(cè)汁咏、語(yǔ)法高亮等等功能,無(wú)需額外的 JS 各種龐雜的工具作媚。
同時(shí)攘滩,這些都是真正的 CSS,并非那些使用了駝峰命名及雙引號(hào)無(wú)處不在的魚目混珠的東西纸泡。
我們可以在 devTools 中對(duì)樣式進(jìn)行修葺調(diào)整漂问,再?gòu)?fù)制粘貼回代碼中,如此行云流水的工作方式弟灼,我再也無(wú)法離開這種酸爽级解。
不得不說(shuō),CSS source maps 功能已是開箱即用的田绑,因此你能快速定位問(wèn)題所在的行勤哗。
其重要性不言而喻:
當(dāng)你使用所見即所得(WYSIWYG)的模式之時(shí),你不會(huì)從組件樹的角度去思考問(wèn)題的掩驱,因此亟需一個(gè)萬(wàn)全之策使有問(wèn)題的樣式原形畢露芒划。
如果組件本就出自他人之手冬竟,情況尤其堪憂。(我敢保證民逼,這種 CSS 工作方式能極大提升你的生產(chǎn)力泵殴,離開 source maps,毋庸置疑你是在虛耗光陰拼苍,因?yàn)槲以?jīng)就是如此笑诅。)
Svelte 轉(zhuǎn)譯你的 CSS 選擇器來(lái)實(shí)現(xiàn)讓樣式只應(yīng)用在局部范圍內(nèi),它同時(shí)也適用于受影響的元素的屬性疮鲫,盡管確切的機(jī)制無(wú)關(guān)緊要吆你,并且可能會(huì)有所變化。
未使用的規(guī)則會(huì)被移除并發(fā)出警告俊犯,然后你可以將精簡(jiǎn)后的結(jié)果寫到 .css
文件中妇多。
還有一個(gè)實(shí)驗(yàn)性的新功能,就是可以編譯組件為 Web Components燕侠,然后將樣式封裝到 shadow DOM 中(如果這剛好就是你所期望的話)者祖。
一切皆有可能,因?yàn)槟愕?CSS 在標(biāo)記的上下文中被解析(使用 css-tree)和靜態(tài)分析绢彤。
靜態(tài)分析為未來(lái)各種令人振奮的可能性打開大門:更智能的優(yōu)化手段七问,各種提示……
但是如果你的樣式需要在運(yùn)行時(shí)才去動(dòng)態(tài)計(jì)算的話,則做這些事情要困難得多杖虾。
我們也才剛剛開始烂瘫。
但我們也可以借助工具來(lái)做啊 [X]媒熊!
如果你看了視頻后的反應(yīng)是:“很好奇适,但是 —— 我們使用 TypeScript,且為各種編輯器編寫插件芦鳍,也能獲得自動(dòng)完成和語(yǔ)法高亮的功能啊嚷往。”
換而言之柠衅,為了獲得與 CSS 等價(jià)的效果皮仁,而去折騰構(gòu)建、文檔菲宴、推進(jìn)及維護(hù)等等一堆輔助性的項(xiàng)目贷祈,如果你認(rèn)為這些事情意義重大……
那么,多說(shuō)無(wú)益喝峦,你和我是道不同势誊,不相為謀了!
我們?nèi)匀粵]有全部答案
綜上所述谣蠢。
誠(chéng)然粟耻,CSS-in-JS 確實(shí)對(duì)一些懸而未決的問(wèn)題給出了答案:
如何從 npm 安裝樣式查近?
我們?nèi)绾沃赜靡恍┒x在同一個(gè)地方的常量?
如何組合聲明挤忙?
就個(gè)人而言霜威,我認(rèn)為所得的好處,沒有超出上述這些問(wèn)題的范圍册烈。
你的選擇可能有不同的優(yōu)先次序戈泼,使你放棄 CSS 有足夠的理由。
但總的來(lái)說(shuō)赏僧,你還是必須了解 CSS 的矮冬,不論熱愛還是憎惡,最終都在所難免要學(xué)習(xí)它次哈。
作為 Web 的守望者胎署,我們可以做選擇:
創(chuàng)建高深莫測(cè)的抽象,讓 Web 開發(fā)者的學(xué)習(xí)曲線更加陡峭窑滞,或者一起解決 CSS 糟粕部分琼牧。
怎么選擇,我已心中有數(shù)哀卫。
<The End>
- 窗明幾凈巨坊,靜候時(shí)日變遷 -