前端CSS的工程化——掌握Sass這四大特性就夠了

来源:http://www.cnblogs.com/iovec/archive/2017/12/11/8024408.html
-Advertisement-
Play Games

記得剛遇見css的時候,咱像是見了美人兒一樣,簡直是愛不釋手啊,簡簡單單寫幾行算不上代碼的代碼,就能做出這麼漂亮的東西,這也成了咱前端之路的最初動力。然而,隨著項目體量和頁面複雜度的增加,咱很快就發現這美人兒非但不漂亮,而且缺胳膊少腿兒的。 ...


初遇 CSS,一見傾心

記得剛遇見css的時候,咱像是見了美人兒一樣,簡直是愛不釋手啊,簡簡單單寫幾行算不上代碼的代碼,就能做出這麼漂亮的東西,這也成了咱前端之路的最初動力。

然而,隨著項目體量和頁面複雜度的增加,咱很快就發現這美人兒非但不漂亮,而且缺胳膊少腿兒的:

  • 缺少模塊系統。模塊系統是軟體工程化的基石,CSS 的這個缺陷對前端項目的工程化管理造成了很大阻力,導致開發大型應用時編碼和維護都異常困難。js 一開始也沒有模塊系統,後來各種輪子頻出,什麼CMD,AMD,UMD全蹦出來了,亂哄哄的,好在 ES6 從語言層面引入了模塊系統才終結了這種亂象,以後 js 的模塊化終於可以統一了。css 你怎麼不好好向你的好基友 js 學習呢,人家都有了,你還傻了吧唧的一點動靜都沒有。
  • 沒有變數機制。這對控制多個地方會引用到的屬性值很不方便。比如一個顏色值,頁面好多地方用到,設計MM突然心血來潮把這個值換成了另一個顏色,咱們怎麼辦,ctrl+f 全局替換?萬一換掉了不該換的,或者漏掉了幾個怎麼辦。
  • 嵌套的層級寫法非常蛋疼。經常會出現
    .page .content .left-side .profile .name{};
    .page .content .left-side .profile .age{};
    這種看起來很不爽,寫起來更不爽的寫法。這是程式員最不能忍受的——重覆。
  • 復用困難。復用是軟體工程的核心思想,css 不僅沒提供模塊系統,而且巧妙地避開了工程化的諸多實踐。更加覺得 css 這門語言設計的跟鬧著玩兒似的。
  • blabla.. 其它的都不是很嚴重啦。
CSS 沒有模塊系統,你當我 @import 是空氣?CSS 的 @import 規則是可以在一個 css 文件導入其他 css 文件,但這貨需要執行到它時才能觸發瀏覽器去下載它所 import 來的 css 文件,導致頁面載入起來特別慢,還不如直接在 <head> 里寫一大坨 <link> 標簽的引入效率高,是名副其實的雞肋功能,演員一般的存在,用你一次算我輸。

有需求就會有市場,Sass(Syntactically Awesome Style Sheets) 應運而生。

老規矩,先來看看 Sass 官網的原話:

Sass 是世界上最成熟、最穩定、最強大的專業級 CSS 擴展語言!

這貨還真是一點也不謙虛,“最成熟,最穩定,最強大”。

通過這幾年項目中的實際運用,咱發現這句簡短霸氣的描述其實並沒有絲毫的浮誇,Sass 的確厲害,完全可以 hold 住這三個“最”字,實至名歸。

什麼是預處理器預處理器是在程式源文件被編譯之前根據預處理指令對程式源文件進行處理的程式。說白了,預處理器只不過是一個文本替換工具而已。CSS 預處理器則是通過將有特殊語法和指令的源代碼處理成瀏覽器可使用的 CSS 文件的程式。
是 Sass 還是 SCSS?SCSS 是 Sass 3 引入的新語法,語法上完全相容原生 CSS,功能上完全繼承 Sass,可以說是 CSS 和 Sass 的完美融合。SCSS 之於 Sass 猶如 CSS3 之於 CSS,ES6 之於 JS。所以別糾結,其實是一個東西啦。

接下來就細數 Sass 帶給咱們的四大實用特性,想必你一定已經使用過它們中的一個或幾個。

一、嵌套寫法

想想之前咱們是怎樣寫原生 css 的:

 .page .content .left-side .profile .name{
     font-size: 2rem;
 }
 .page .content .left-side .profile .age{
     color: red;
 }

現在使用 scss 可以這樣寫:

.page{
    .content{
        .left-side{
            .profile{
                .name{
                    font-size: 2rem;
                }
                .age{
                    color: red;
                }
            }
        }
    }
}

編譯後

.page .content .left-side .profile .name{font-size: 2rem;}
.page .content .left-side .profile .age{color: red;}

這種嵌套寫法的好處是顯然的:

  • 結構清晰簡潔,並且可與 html 文檔結構對應起來;
  • 減少了大量冗餘重覆的選擇器編碼;

二、屬性值的復用——定義變數

變數一直是所有編程語言的標準配置。然而 CSS 就沒有,再次證明 CSS 可能是一門假語言。好在 Sass 補上了這個短板。

沒有變數之前的代碼(這裡以定義一系列表示成功風格的樣式組件為例):

.success-bg{
    background: #dff0d8;
}
.success-panel{
    .panel-heading{
        background: #dff0d8;
    }
    .panel-body{
        border: 1px solid #dff0d8;
    }
}

使用了變數後的代碼:

$success-color: #dff0d8;

.success-bg{
    background: $success-color;
}
.success-panel{
    .panel-heading{
        background: $success-color;
    }
    .panel-body{
        border: 1px solid $success-color;
    }
}

使用變數的好處是顯而易見的:

  • 方便了多人協同作戰,將頻繁使用的屬性值定義成變數放在單獨的文件里,各個開發人員可方便引用而不必再關註這些小細節,有語義的變數名使用起來也要比單調的CSS值容易的多;
  • 極大地增強了代碼的可維護性,便於局部和全局的樣式風格統一控制;

三、文件級的復用——模塊系統

模塊化是軟體工程的第一要務,是大型項目的必需建築。軟體工程的主要目標就是控制複雜度,這也正是模塊化的目的。通過將一個大型複雜的工程拆解成一個個的小模塊,使得校驗、調試、測試都輕而易舉。

CSS原生的 @import 提供了一個並沒有卵用的假模塊系統。Sass 對 @import 進行了拓展,實現了一個真正意義上甚至功能更強大的模塊系統。Sass 選擇對 @import 進行擴展,而不是新建一個指令,可見 import 這個關鍵字的語義之強,JavaScript 模塊系統的關鍵字也是 import

沒有模塊系統之前:

<!-- index.html -->
<link rel="stylesheet" href="/your/site/common.css">
<link rel="stylesheet" href="/your/site/popup.css">
<link rel="stylesheet" href="/your/site/module_a.css">
<link rel="stylesheet" href="/your/site/site.css">

有了模塊系統之後:

/* site.scss */
@import "common";
@import "popup";
@import "module_a";
<!-- index.html -->
<link rel="stylesheet" href="/your/site/site.css">

好處嘛自然不用多說了:

  • 增刪改模塊以後是 css 自己家的事,別麻煩別人,不用再去動 html 了吼;
  • 模塊系統使得項目並不會隨著業務複雜度增加而變得更加複雜。增加功能時只需要橫向擴展就行了,不會縱向延伸,從而能始終保證每個模塊完整而簡單;

四、展示層的復用——混合指令

混合(mixin)特別類似於 JavaScript 中的函數,然而 Sass 提供了用於表達式計算的 @function 函數指令,這裡就不好這麼類比了。但其實就是這麼個東西,調用的時候會返回一段樣式。

比如下麵一段存在重覆樣式的代碼。

復用之前:

.description{
    color: red;
    border: 1px solid #e3e3e3;
    border-radius: 2px;
}
.article{
    color: #444;
    border: 1px solid #e3e3e3;
    border-radius: 2px;
}

稍作優化:

.description, .article{
    border: 1px solid #e3e3e3;
    border-radius: 2px;
}
.description{
    color: red;
}
.article{
    color: #444;
}

似乎不錯,但是之後再新加類似樣式時,

.description, .article, .style01, .style02{
    border: 1px solid #e3e3e3;
    border-radius: 2px;
}
.
.
.
.style01{}
.style02{}

每次都要改兩個地方,很麻煩,很容易漏,尤其是將通用樣式分離出來的話更容易出錯。

再做優化:

.grey-border-radius{
    border: 1px solid #e3e3e3;
    border-radius: 2px;
}
.description{
    color: red;
}
.article{
    color: #444;
}

似乎好了一點,但這樣的話,html 每個使用的標簽都需要多加上一個 .grey-border-radius 類。很顯然這是多餘的。這種做法可以說是“湊合”。

使用 Sass 復用之後:

@mixin grey-border-radius{
    border: 1px solid #e3e3e3;
    border-radius: 2px;
}
.description{
    @include grey-border-radius;
    color: red;
}
.article{
    @include grey-border-radius;
    color: #444;
}

編譯後的 css 輸出:

.description {
  border: 1px solid #e3e3e3;
  border-radius: 2px;
  color: red;
}
.article {
  border: 1px solid #e3e3e3;
  border-radius: 2px;
  color: #444;
}

看到了吧,這種做法簡直“完美”:

  • 抽離公共的樣式片段,便於多處復用;
  • 將公共的樣式片段放在單獨的文件里,便於項目的多個文件復用;
  • 對 html 的使用沒有任何要求,css 自己家的事自己關起門來解決,絕不麻煩別人;

其他不常用且慎用的強大特性

如果熟練合理地運用上面的四大特性,你已經是CSS代碼工程化方面的磚家了,所寫出來的代碼必是清晰易維護的。Sass 提供了更多的功能,但對普通開發者來講,上面的四點只要使用熟練,已經完全夠用了,其他的可看可不看。下麵提供的功能希望大家慎用,有的是出於性能考慮,有的則是從開發維護的角度考慮。尤其不要為了秀技術而去使用它們,過猶不及,事緩則圓,此為中庸之道。

語義層的復用——繼承機制

繼承是面向對象程式設計的三大特性之一,這也是為什麼說它是語義層復用的原因。你可以說一個錯誤信息框繼承了一個信息框,而不能說一個錯誤信息框繼承了一個灰色圓角,雖然也是可以強行這麼說,但難免有些彆扭哈哈。

比如說下麵定義一組信息框的樣式,包括預設,成功和錯誤的樣式。

使用繼承之前:

.msg{
    border: 1px solid #e3e3e3;
    background: #dff0d8;
}
.msg-success{
    color: #4cae4c;
}
.msg-error{
    color: #d43f3a;
}

同樣是上面說到的問題,編寫 html 時每個使用的標簽都需要多加上一個 .msg 類,很多餘。

使用繼承之後:

.msg{
    border: 1px solid #e3e3e3;
    background: #dff0d8;
}
.msg-success{
    @extend .msg;
    color: #4cae4c;
}
.msg-error{
    @extend .msg;
    color: #d43f3a;
}

編譯後

.msg, .msg-success, .msg-error {
  border: 1px solid #e3e3e3;
  background: #dff0d8;
}
.msg-success {
  color: #4cae4c;
}
.msg-error {
  color: #d43f3a;
}

可以看出,上面的效果使用混合(mixin)也可以完成。但不同的是:繼承拷貝的是選擇器,而混合(mixin)拷貝的是樣式片段。

使用混合(mixin)還是繼承(extend)?你肯定以為既然繼承拷貝的是選擇器,而混合拷貝的是大段的樣式,那當然是優先選擇繼承了。然而恰恰相反,推薦做法是儘可能使用混合(mixin),具體原因 戳這裡

用於複雜計算的函數

這個功能主要用於值的計算,和 JavaScript 中的函數類似。

比如移動端開發時可以封裝成一個函數用於把 px 轉成 rem。

$baseFontSize: 20;
@function px2rem($val) {
  @return $val/$baseFontSize + rem;
}

.big-text{
    font-size: px2rem(30);
}

編譯後:

.big-text {
  font-size: 1.5rem;
}

這樣在拿到設計MM給的視覺稿之後就可以直接使用 px 進行測量使用了。

完善的控制流

控制流即程式語言中的 if/elseforwhile 等控制語句。Sass 同樣提供了指令實現:

  • @if
  • @for
  • @each
  • @while

它們通常配合 @function 指令使用,然而功能雖強,卻不常用到。畢竟樣式表的功用主要是描述頁面樣式,而不是提供更多控制。因此在這裡不展開研究,感性趣的戳這裡

小結

Sass 完美彌補了上面原生 CSS 暴露的幾個短板,同時新語法 SCSS 使 CSS 開發者可以無縫過渡,是 CSS 預處理器中當之無愧的佼佼者。使用 Sass 容易編寫出結構清晰,可復用,易維護的工程樣式文件,這正是工程化的期望。這麼好的東西,速速用起來。

本文主要參考了 Sass 中文網


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一旦攻擊者將植入惡意代碼的仿冒的App投放到安卓商店等第三方應用市場,就可替代原有的App,進行公開下載、更新。網友安裝這些仿冒App後,不僅會泄露個人賬號、密碼、照片、文件等隱私信息,手機更可能被植入木馬病毒,進而或導致手機被ROOT,甚至被遠程操控。 ...
  • dispatch_sync 線程同步、dispatch_async線程非同步 比如 這些代碼輸出的結果是 1 2 3 4 依次輸出、無論你運行多少次都會是這一種結果 但是來看下麵的非同步呢? 輸出的結果是 1 2 3 4 隨機輸出、有時 2 1 3 4 有時 1 3 2 4 等 在iOS中是無法使用 d ...
  • [1]定義 [2]參數傳遞 [3]返回值輸出 [4]AOP [5]其他應用 ...
  • 很久不寫文檔,平時只寫日記,所以對這個有點生疏,如果寫的不好別介意。 今天閑的蛋疼,於是要寫寫白天的東西,並且以後也會一直更新(一直寫)下去。 時間太倉促了,這幾個月,今天算最晚的一次凌晨1點,吃不消的路過。 進入正題! 這是一個每次點擊添加指定數據的插件,基於jQuery封裝,調用方法名batch ...
  • 設置cookie: ...
  • 上一節看了一眼預編譯的總體代碼,這一節分析convert-argv模塊。 這個模塊主要是對命令參數的解析。 生成預設配置文件名數組 函數內部,首先判斷了argv.d與argv.p屬性是否存在,這個屬性來源於參數d與p,即webpack -d -p,測試如圖: 因為懶得加,所以直接跳過,進入到第二階段 ...
  • 前端體系的變化可謂是日新月異,短短一年時間,從理論、框架、構建工具、甚至開發語言都發生非常大的變化。 隨著新項目就即將啟動,我抽時間回顧了一下以往項目的前端架構,零零散散產生了許多想法,儘量一一記錄下來,為新的框架搭建做點準備。 首先來聊聊CSS的的各種規範與理論。回顧過去的代碼,首先讓我頭痛不已的 ...
  • 頁面中任何一個元素都可以指定為 彈性佈局(Flex) 屬性:display 取值: 1、flex 將塊級元素變為彈性佈局容器 2、inline-flex 將行內元素變為彈性佈局容器 相容性: display:-webkit-flex; 註意:將元素設置為flex後,子元素的 float,clear以 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...