為什么會出現(xiàn)CSS預(yù)編譯器這個東西呢?這就要談到CSS的不足了:沒有變量(新的" />

国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

15158846557 在線咨詢 在線咨詢
15158846557 在線咨詢
所在位置: 首頁 > 營銷資訊 > 網(wǎng)站運(yùn)營 > CSS預(yù)編譯器三劍客及PostCSS

CSS預(yù)編譯器三劍客及PostCSS

時(shí)間:2023-09-10 18:30:02 | 來源:網(wǎng)站運(yùn)營

時(shí)間:2023-09-10 18:30:02 來源:網(wǎng)站運(yùn)營

CSS預(yù)編譯器三劍客及PostCSS:這篇文章包含兩個部分,第一部分是個CSS預(yù)編譯器:Sass、Less、Stylus,他們之間的對比,第二部分是現(xiàn)在大火的PostCSS。

為什么會出現(xiàn)CSS預(yù)編譯器這個東西呢?這就要談到CSS的不足了:沒有變量(新的規(guī)范已經(jīng)支持了),不支持嵌套,編程能力較弱,代碼復(fù)用性差。這些不足導(dǎo)致寫出來的CSS維護(hù)性極差,同時(shí)包含大量重復(fù)性的代碼;為了彌補(bǔ)這些不足之處,CSS預(yù)編譯器應(yīng)運(yùn)而生。而談到CSS預(yù)編譯器,就離不開這三劍客Sass、Less、Stylus。歷史上,最先登場的是Sass,因?yàn)槌霈F(xiàn)最早,所以也是最完善的,有各種豐富的功能;Less的出現(xiàn)伴隨著Bootstrap的流行,因此也獲得大量用戶;最后是Stylus,由TJ大神開發(fā)(敬大神),由于其簡潔的語法,更像是一門編程語言,寫起來非常Cool。所以下面我們來做一個簡單的對比。

Less & SCSS.wrap { display: block;}Sass.wrap display: blockStylus.wrap display blockSass最開始通過縮進(jìn),空格,換行的形式來控制層級關(guān)系,寫過Python的同學(xué)一定不會陌生,后來又支持了傳統(tǒng)的類CSS語法的Scss。Less中規(guī)中矩,使用CSS的風(fēng)格,對新手非常友好,也利于現(xiàn)有項(xiàng)目的遷移。Stylus既可以使用Sass風(fēng)格的語法來編寫,也兼容CSS的風(fēng)格。

這三者都支持變量的定義,而定義方式又各不相同:

Less:@smallFont: 12px;small { font-size: @smallFont;}Sass$smallFont: 12px;small { font-size: $smallFont;}StylussmallFont = 12pxsmall font-size smallFont


需要注意的是:Stylus中聲明的變量,如果變量名跟CSS中的字面值相同時(shí),會覆蓋CSS中的字面值。

有一個好玩的東西:相信大家平時(shí)都或多或少會接觸到組件庫,組件庫的編寫中會使用到CSS的預(yù)編譯器來編寫樣式,通過外部傳入變量的方式來提供自定義樣式的功能,就像Ant.design和ElementUI那樣。這就涉及到CSS變量的作用范圍了,在這三種中預(yù)編譯中,Sass/Stylus是相同的,Less是另一種情況,下面看實(shí)例:

Less@color: red;.content-1 { color: @color;}@color: black;.content-2 { color: @color;}/* 編譯出來的CSS*/.content-1 { color: black;}.content-2 { color: black;}Less中的變量,在聲明中使用時(shí),如果出現(xiàn)多次賦值的情況,其會取最后一次賦值的值,這也就是上面的.content-1, content-2中的color都是black的原因?;贚ess中變量的這個特性,我們可以很輕易的改變原有組件庫或者類庫中變量的值,只需要在引入Less文件后,對特定的變量賦值即可。同時(shí)也會帶來一定的隱患:如果不同的組件庫或類庫使用了相同的變量名,那么就會出現(xiàn)覆蓋的情況,所以應(yīng)該采用模塊化的方式。

Sass$color: red;.content-1 { color: $color;}$color: black;.content-2 { color: $color;}Styluscolor = red;.content-1 color colorcolor = black;.content-2 color color;/* 編譯出來的CSS*/.content-1 { color: red;}.content-2 { color: black;}上面我們可以看到,Sass/Stylus中的變量,如果出現(xiàn)多次賦值的情況,其會取聲明前面最近的一次賦值的值,這就是為什么.content-1的color為red,.content-2的color為black的原因。同時(shí),在Sass/Stylus編寫的不同組件庫或類庫中的變量,不會出現(xiàn)沖突,但是這就為通過覆蓋變量的值來自定義樣式提出了挑戰(zhàn),我們應(yīng)該怎么做呢?考點(diǎn)來了,Sass/Stylus中提供了"不存在即賦值"的變量聲明:

Sass$a: 1;$a: 5 !default;$b: 3 !default;// $a = 1, $b = 3Stylusa = 1a := 5 b = 3// a = 1, b = 3細(xì)看代碼,你一定會明白:使用"不存在即賦值"語法,編譯器會檢查前面是否定義了同名變量,如果沒有定義,執(zhí)行變量定義;如果前面定義了同名變量,則不會執(zhí)行這個賦值的操作。因此,我們可以在使用了Sass/Stylus的組件庫或類庫中使用"不存在即賦值"的方式來定義變量,在引入之前定義好需要同名變量,就能達(dá)到目的了。

同時(shí),我們定義的變量不僅能用作CSS聲明的值,同時(shí)也能嵌套到選擇器及屬性中:

Less@prefix: ui;@prop: background;.@{prefix}-button { @{prop}-color: red;}Sass$prefix: ui$prop: background;.#{$prefix}-button{ #{$prop}-color: red;}Stylusprefix = uiprop = background.{prefix}-button {prop}-color red變量相關(guān)的內(nèi)容基本上覆蓋到了,接下來就是樣式的復(fù)用了。提到樣式復(fù)用,必定會提到mixin和繼承了。對于mixin,這三個預(yù)編譯器也都有不同的實(shí)現(xiàn)方式:

Less:.mixin-style(@color: red) { color: @color;}.content { .mixin-style(red);}Sass:@mixin mixin-style { color: red;}.content { @include mixin-style;}Stylus: mixin-style(color) color color .content mixin-style(red) // or mixin-styls red 透明mixin在Less中,可以直接引入一個CSS的class作為mixin(這種方式非常不推薦), 同時(shí)也提供上面的能夠傳入?yún)?shù)的mixin;Sass比較中規(guī)中矩,通過@mixin和@include的方式定義和引入mixin;Stylus不需要顯示的聲明mixin,同時(shí)還提供透明mixin的功能,就像屬性一樣引入。

接下來就會講到繼承了,這其中,Sass/Stylus通過@extend關(guān)鍵字來繼承樣式,而Less通過偽類的方式來繼承:

Sass/Stylus:.message{ padding: 10px; border: 1px solid #eee;}.warning{ @extend .message; color: #e2e21e}Less:.message { padding: 10px; border: 1px solid #eee;}.warning { &:extend(.message); color: #e2e21e;}個中優(yōu)劣,大家可以自己評判。更多詳細(xì)的對比,可以查看顧軼靈大神的文章。

聊完了CSS預(yù)處理器,我們接下來聊聊大火的PostCSS。說到PostCSS,大家總會問,PostCSS是什么?這個問題,我們來看看官網(wǎng)對它的定義吧:

PostCSS is a tool for transforming styles with JS plugins. These plugins can lint your CSS, support variables and mixins, transpile future CSS syntax, inline images, and more.
所以我的理解是,PostCSS是一個使用JS插件來轉(zhuǎn)換樣式的工具。PostCSS跟CSS預(yù)處理器的定位不同,看了前面的內(nèi)容,大家都知道CSS預(yù)處理器的作用是什么,而PostCSS的作用主要有l(wèi)int css,支持CSS Next語法,自動添加前綴等等功能,通過插件,基本上可以覆蓋CSS 預(yù)處理器的功能,同時(shí)實(shí)現(xiàn)多得多的預(yù)處理器實(shí)現(xiàn)不了的功能。既然PostCSS這么牛逼,那我們來深入研究一下。

對于PostCSS,首先需要了解的有這么幾個點(diǎn):

  1. PostCSS不是CSS預(yù)處理器的替代品,雖然真的可以用PostCSS來替換掉。對于現(xiàn)有的項(xiàng)目,能夠很容易的使用上PostCSS,無論你使用的是哪一個預(yù)處理器或者哪一個構(gòu)建工具,都不會有太大的遷移成本。
  2. PostCSS的優(yōu)勢在于其豐富的插件生態(tài),能夠覆蓋開發(fā)中的方方面面,我們又能夠很容易的開發(fā)自己的插件。同時(shí)又因?yàn)镻ostCSS使用Javascript,Javascript本身及其繁榮的生態(tài),為PostCSS提供了更加強(qiáng)大的能力。
  3. PostCSS中,最為大家所熟知的就是Autoprefix,同時(shí)Autoprefix在大量的預(yù)處理中使用著。PostCSS依靠其現(xiàn)代的架構(gòu)設(shè)計(jì),甩掉了歷史包袱,利用其插件系統(tǒng),能夠更加優(yōu)雅強(qiáng)化CSS的健壯性
PostCSS架構(gòu)大致如下圖:







通過PostCSS將CSS轉(zhuǎn)換成AST(抽象語法樹),對應(yīng)的是JavaScript對象;然后通過插件遍歷AST,進(jìn)行增加,刪除,修改;最后再生成CSS文件,這就是整個流程,跟babel的架構(gòu)非常相似。

其中的CSS解析成AST及AST序列化生成CSS,PostCSS都幫我們做好了,我們只需要關(guān)注在插件開發(fā),及如何操作AST。

所以下面我們用一個簡單的例子來說明如何開發(fā)PostCSS的插件。有這么一個樣式:

.content{ color: red;}如果我們檢測到某個樣式中有"color: red"這樣一條樣式規(guī)則,需要自動增加"background-color: red"這樣一條規(guī)則。

PostCSS官方提供插件編寫的模板,只需要將其下載下來:

git clone git@github.com:postcss/postcss-plugin-boilerplate.git



然后進(jìn)入該文件夾的目錄下,輸入命令:

node start
這個時(shí)候會需要你輸入一些信息,然后就會自動生成一個插件的模板文件夾,還是進(jìn)入到這個對應(yīng)的文件夾下,這個時(shí)候就能看到熟悉的package.json,index.js等文件,使用npm安裝了依賴之后就可以在index.js文件中編寫插件的邏輯了。同樣的,我們可以在項(xiàng)目中通過npm安裝任意依賴,然后在index.js中通過require引入,這就是背靠JavaScript的優(yōu)勢。

index.js默認(rèn)的內(nèi)容是這樣的:

var postcss = require('postcss');module.exports = postcss.plugin('postcss-practice', function (opts) { opts = opts || {}; // Work with options here return function (root, result) { // Transform CSS AST here };});編寫出來的插件代碼是這樣的:

const postcss = require('postcss');const postcss = require('postcss');module.exports = postcss.plugin('postcss-practice', function (opts) { opts = opts || {}; console.log(opts); // Work with options here return function (root) { root.walkRules(rule => { console.log(rule.selector); rule.walkDecls(decl => { if ( decl.prop === 'color' && decl.value === 'red' ) { rule.append({ prop: 'background-color', value: 'red' }); } }); }); };}); 非常簡單,解釋一下:root.walkRules會遍歷每一個CSS規(guī)則,可以通過rule.selector拿到每一組規(guī)則中的選擇器,然后通過rule.walkDecls遍歷每一組規(guī)則中的樣式聲明, 通過decl.prop,decl.value拿到樣式聲明中的屬性和值。上面判斷屬性是否為'background-color'、值是否為'red',如果滿足條件則向規(guī)則中插入一條新的樣式聲明(這里為了簡單,沒有考慮是否已經(jīng)存在background-color聲明)。

插件編寫完了,樣板項(xiàng)目中還包含index.test.js來測試是否插件是否合理,下面是編寫的index.test.js中的測試代碼:

var postcss = require('postcss');var plugin = require('./index.js');function run(input, output, opts) { return postcss([ plugin(opts) ]).process(input) .then(result => { expect(result.css).toEqual(output); expect(result.warnings().length).toBe(0); });}// Write tests hereit('does something', () => { return run('a{color: red;}', 'a{color: red;background-color: red;}', {});});然后是運(yùn)行: "npm run test"的結(jié)果:

接下來就可以打包發(fā)布,然后在項(xiàng)目中安裝使用了,就像其他插件那樣。PostCSS還提供了許多有用的函數(shù),幫助你操作AST,輕松完成開發(fā)。



關(guān)鍵詞:編譯

74
73
25
news

版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。

為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點(diǎn)擊下載Chrome瀏覽器
關(guān)閉