• <sub id="h4knl"><ol id="h4knl"></ol></sub>
    <sup id="h4knl"></sup>
      <sub id="h4knl"></sub>

      <sub id="h4knl"><ol id="h4knl"><em id="h4knl"></em></ol></sub><s id="h4knl"></s>
      1. <strong id="h4knl"></strong>

      2. CSS預(yù)處理語(yǔ)言的模塊化實(shí)踐實(shí)例

        時(shí)間:2024-11-01 11:49:33 CSS 我要投稿
        • 相關(guān)推薦

        CSS預(yù)處理語(yǔ)言的模塊化實(shí)踐實(shí)例

          編寫(xiě)css是前端工作中,一項(xiàng)普通而又頻繁的勞動(dòng),由于css并不是一門(mén)語(yǔ)言,所以在程序設(shè)計(jì)上顯得有些簡(jiǎn)陋。對(duì)于小型項(xiàng)目來(lái)說(shuō),css的量還不至于龐大,問(wèn)題沒(méi)有凸顯,而如果要開(kāi)發(fā)和持續(xù)維護(hù)一個(gè)較為大型的項(xiàng)目,那就需要對(duì)css進(jìn)行管理和規(guī)范了,否則會(huì)發(fā)生不可挽回的后果。

          通過(guò)規(guī)范的約束,將css的編寫(xiě)方式進(jìn)行了優(yōu)化和改進(jìn),形成一種可持續(xù)發(fā)展的路線。但還是遺留了一些問(wèn)題:冗余。雖然我們通過(guò)定義公共模塊和私有模塊,來(lái)委婉地分擔(dān)common的體積,但common的體積還是太大了,而且從設(shè)計(jì)上考慮,我們應(yīng)該盡量多地提煉公共模塊,以便更好地實(shí)現(xiàn)復(fù)用。最理想的情況是,所有的模塊都寄存在一個(gè)公共的庫(kù)里,哪里需要用到就從庫(kù)中直接調(diào)過(guò)來(lái)。這個(gè)美好的愿望不是不可實(shí)現(xiàn)的,借助預(yù)處理語(yǔ)言,我們可以很輕易地完成這事情。

          預(yù)處理語(yǔ)言是一種類(lèi)css的語(yǔ)言,我們知道css本身不是語(yǔ)言,而預(yù)處理語(yǔ)言的誕生,就是為填補(bǔ)這一部分語(yǔ)言功能。它實(shí)現(xiàn)了變量、函數(shù)、混合的定義,以及文件的引用、合并、壓縮功能,使得css也能面向?qū)ο螅瑧?yīng)付復(fù)雜龐大的業(yè)務(wù)。

          目前流行的預(yù)處理語(yǔ)言主要有兩種:less和sass。作為學(xué)習(xí),兩者都可以入門(mén)一下,而作為工作,盡量熟悉一種。我比較常用sass,所以以下內(nèi)容都是以sass為基本語(yǔ)言做介紹,兩者在特性上有很多相似的地方,所以大家不必?fù)?dān)心實(shí)現(xiàn)上有什么千差萬(wàn)別。

          sass

          基本語(yǔ)法可以到官方網(wǎng)(英語(yǔ))或者w3cplus sass guide(中文)查看學(xué)習(xí),我們這里只簡(jiǎn)單地過(guò)一遍,講一些我們需要用到的內(nèi)容,不會(huì)面面俱到。

          sass有兩種后綴名文件:一種后綴名為sass,不使用大括號(hào)和分號(hào);另一種就是我們這里使用的scss文件,這種和我們平時(shí)寫(xiě)的css文件格式差不多,使用大括號(hào)和分號(hào)。而本教程中所說(shuō)的所有sass文件都指后綴名為scss的文件。在此也建議使用后綴名為scss的文件,以避免sass后綴名的嚴(yán)格格式要求報(bào)錯(cuò)。 ——摘自w3cplus sass guide

          1、嵌套(非常重要的特性)

          sass的嵌套包括兩種:一種是選擇器的嵌套;另一種是屬性的嵌套。我們一般說(shuō)起或用到的都是選擇器的嵌套。 ——摘自w3cplus sass guide

          選擇器嵌套 所謂選擇器嵌套指的是在一個(gè)選擇器中嵌套另一個(gè)選擇器來(lái)實(shí)現(xiàn)繼承,從而增強(qiáng)了sass文件的結(jié)構(gòu)性和可讀性。在選擇器嵌套中,可以使用&表示父元素選擇器。 ——摘自w3cplus sass guide

          // index.scss

          .g-index {

          ...

          .g-hd {

          ...

          .m-nav { ... }

          }

          .g-bd {

          ...

          .m-news { ... }

          }

          .g-ft {

          ...

          .m-copy_right { ... }

          }

          .m-dialog {

          display: none;

          &.z-active { // 留意此處&的用法

          display: block;

          }

          }

          }

          編譯后:

          /* index.css */

          .g-index { ... }

          .g-index .g-hd { ... }

          .g-index .g-hd .m-nav { ... }

          .g-index .g-bd { ... }

          .g-index .g-bd .m-news { ... }

          .g-index .g-ft { ... }

          .g-index .g-ft .m-copy_right { ... }

          .g-index .m-dialog {

          display: none;

          }

          .g-index .m-dialog.z-active { // 留意此處&的編譯結(jié)果

          display: block;

          }

          是不是爽歪歪?再也不用一遍一遍地去復(fù)制和修改一大堆的選擇器,也不需要去整理它們之間的關(guān)系,只需要嵌套一下,所有的關(guān)系就如同直接看dom一樣簡(jiǎn)單明了了!解放雙手,解放雙眼,同時(shí)還提高效率。值得留意的是,我們書(shū)寫(xiě)sass的時(shí)候,應(yīng)該盡量保持sass的嵌套順序與dom一致,注意,是嵌套順序一致,而不是層次一致,因?yàn)椴⒉皇莇om里的所有元素都需要寫(xiě)樣式。

          我們?cè)賮?lái)提一個(gè)場(chǎng)景,說(shuō)明sass的嵌套寫(xiě)法利于維護(hù),假設(shè)g-bd下原本有個(gè)模塊m-article_box,現(xiàn)在我們要把m-article_box從g-bd遷移到g-hd中(當(dāng)然這個(gè)需求有些不合理~),我們來(lái)看原始代碼:

          

          

          

          

          titleindex/title

          

          

          


          


          


          


          最新文章

          

          


          


          


          

          


          


          文章標(biāo)題

          

          

        文章簡(jiǎn)介

          

          

          

          

          


          


          1

          2

          3

          4

          

          

          

          

          

          

          

          .g-bd { ... }

          .g-bd .m-article_box { ... }

          .g-bd .m-article_box .hd { ... }

          .g-bd .m-article_box .bd { ... }

          .g-bd .m-article_box .bd .list { ... }

          .g-bd .m-article_box .bd .list .item { ... }

          .g-bd .m-article_box .bd .list .item .cover { ... }

          .g-bd .m-article_box .bd .list .item .info { ... }

          .g-bd .m-article_box .bd .list .item .info .title { ... }

          .g-bd .m-article_box .bd .list .item .info .desc { ... }

          .g-bd .m-article_box .ft { ... }

          .g-bd .m-article_box .ft .page { ... }

          .g-bd .m-article_box .ft .page .pg { ... }

          按照css的方式,我們就要把所有跟m-article_box有關(guān)的部分,從g-bd全部復(fù)制到g-hd里去。這還是在模塊的書(shū)寫(xiě)符合規(guī)范的情況下,如果這個(gè)模塊書(shū)寫(xiě)不符合規(guī)范,沒(méi)有把全部結(jié)構(gòu)都掛在m-article_box類(lèi)下,那真的就是災(zāi)難了~而現(xiàn)在使用sass的話,我們只需要把m-article_box的區(qū)塊整個(gè)從g-bd剪切到g-hd就完事了(這里為了突出修改的工作量大,我特地把整個(gè)模塊結(jié)構(gòu)都寫(xiě)全了——才不是為了湊字?jǐn)?shù)。。。):

          // 修改前

          .g-hd { ... }

          .g-bd {

          .m-article_box {

          .hd { ... }

          .bd {

          .list {

          .item {

          .cover {

          ...

          }

          .info {

          .title {

          ...

          }

          .desc {

          ...

          }

          }

          }

          }

          }

          .ft {

          .page {

          .pg { ... }

          }

          }

          }

          }

          // 修改后

          .g-hd {

          .m-article_box {

          .hd { ... }

          .bd {

          .list {

          .item {

          .cover {

          ...

          }

          .info {

          .title {

          ...

          }

          .desc {

          ...

          }

          }

          }

          }

          }

          .ft {

          .page {

          .pg { ... }

          }

          }

          }

          }

          .g-bd { ... }

          非常方便,而且不容易出錯(cuò)。

          2、變量(variable)

          咱們直接上代碼:

          // index.scss

          $fontSize: 16px;

          $grey: #ccc;

          .m-nav {

          font-size: $fontSize;

          color: $grey;

          }

          編譯結(jié)果:

          /* index.css */

          .m-nav {

          font-size: 16px;

          color: #ccc;

          }

          寫(xiě)過(guò)代碼的人都熟悉 參數(shù) 的用法吧,太簡(jiǎn)單太直白了不想說(shuō)太多,自己意會(huì)吧。

          3、函數(shù)(function)

          // pixels to rems

          @function rem($px) {

          @return $px / 640 * 16rem;

          }

          太簡(jiǎn)單了直白了不想說(shuō)太多,自己意會(huì)吧。

          4、混合(mixin)

          混合,顧名思義,就是混合的意思。。。也就是我們可以事先定義一段代碼塊,在需要使用到的地方,直接引用(include),而在引用之前,這段代碼都不會(huì)出現(xiàn)在編譯文件中,也就是不會(huì)生成任何內(nèi)容。

          這也是非常重要的一個(gè)特性!我們知道common的體積非常大,而體積大的根本原因是它存放了許許多多的模塊。我們?cè)O(shè)想一下,如果將每一個(gè)模塊都打包成mixin,那common不就減肥成功了?!多年的頑疾終于看到希望,沒(méi)有比這更讓人驚喜的了!我們這就上車(chē):

          /* common.css */

          .m-nav { ... }

          .m-news { ... }

          .m-copy_right { ... }

          改造后

          // common.scss

          @mixin m-nav {

          .m-nav { ... }

          }

          @mixin m-news {

          .m-news { ... }

          }

          @mixin m-copy_right {

          .m-copy_right { ... }

          }

          // index.scss

          .g-index {

          @include m-nav;

          @include m-news;

          @include m-copy_right;

          }

          5、import

          這個(gè)屬性很眼熟?沒(méi)錯(cuò),事實(shí)上,css本身就有這個(gè)屬性實(shí)現(xiàn),我們可以在css文件中直接使用import來(lái)引入其他文件。那么css的import和sass的import有什么區(qū)別?從含義和用法上來(lái)說(shuō),沒(méi)有區(qū)別,區(qū)別在于工作原理。css的import是阻塞的,而sass的import在編譯后,其實(shí)是合并文件,最后只產(chǎn)出一個(gè)css文件,而css則沒(méi)有合并,該多少個(gè)文件就還是多少個(gè)文件。

          注意:

          只有import一個(gè).sass/.scss文件的時(shí)候,才可以省去后綴名,如果是直接import一個(gè).css文件,要補(bǔ)全文件名;

          import之后的分號(hào);不要漏寫(xiě),會(huì)報(bào)錯(cuò);

          sass如果import的是一個(gè).css文件的話,那它的作用就跟css原生的import作用一樣,只有import一個(gè)sass文件的時(shí)候,才是合并文件。

          如下:

          // index.scss

          @import 'common';

          @import 'a.css';

          編譯結(jié)果:

          /* index.scss */

          .m-nav { ... }

          .m-news { ... }

          .m-copy_right { ... }

          @import url('a.css');

          css的import之所以沒(méi)有被普遍使用是有原因的。我們可以大概猜到它的工作原理:a.css import b.css以后,當(dāng)瀏覽器加載到頁(yè)面中的a.css的時(shí)候,已經(jīng)準(zhǔn)備按照a.css的內(nèi)容來(lái)渲染頁(yè)面了,剛解析到第一行,發(fā)現(xiàn)a.css居然還import了一個(gè)b.css,于是它不得不先放下a.css(既阻塞a.css),去加載b.css,直到b.css加載完,并且優(yōu)先解析它,然后才開(kāi)始回來(lái)解析a.css——鬼知道b.css會(huì)不會(huì)又import了c.css……這直接導(dǎo)致了渲染工作滯后,引發(fā)性能問(wèn)題。

          說(shuō)實(shí)話我還不如直接用兩個(gè)link標(biāo)簽去同步加載a.css和b.css,效率會(huì)高一些。

          所以css的import基本是被拋棄了的屬性。

          sass的import主要的好處就是把文件合并了,減少了請(qǐng)求。原本需要link好幾個(gè)css文件的頁(yè)面,現(xiàn)在只需要一個(gè)。

          模塊化

          終于要開(kāi)始干點(diǎn)正事了,首先我們來(lái)回顧一下,上一節(jié)我們以規(guī)范為基礎(chǔ)構(gòu)建的模塊化項(xiàng)目,遺留了一些什么問(wèn)題。

          冗余 體積龐大的common;

          使用cm-模塊區(qū)別m-模塊,使得后期開(kāi)發(fā)過(guò)程中,m-模塊向cm-模塊轉(zhuǎn)變過(guò)程比較繁瑣;

          ……

          好像,問(wèn)題也不是特別多,我們一個(gè)一個(gè)解決。

          為了方便,在這里我們把每個(gè)頁(yè)面所對(duì)應(yīng)的scss文件叫做 頁(yè)面scss;把變量、函數(shù)、混合等(沒(méi)有被引用或者執(zhí)行的情況下)編譯后不產(chǎn)生實(shí)際內(nèi)容的代碼叫做 定義類(lèi)代碼 ,那么相對(duì)應(yīng)的其他內(nèi)容就是 實(shí)際內(nèi)容代碼。

          1、mixin.scss

          我們知道,一方面,在common中過(guò)多地添加模塊最終會(huì)導(dǎo)致common的體積過(guò)大,使得資源冗余,另一方面,為了方便維護(hù),我們又希望盡量多地把模塊公有化。

          這是一對(duì)矛盾,僅靠css本身是無(wú)法解決的,但sass可以!如果我們使用mixin來(lái)代替直接書(shū)寫(xiě)模塊,由于mixin并不直接生成代碼,而是通過(guò)主動(dòng)引用,才能生成對(duì)應(yīng)內(nèi)容,那么理論上,common就可以無(wú)限多地存放模塊而不必占用一點(diǎn)空間!

          (注意,這里說(shuō)的是理論上,實(shí)際應(yīng)用中,文件太過(guò)龐大的話,免不了還是要受到命名沖突的限制的,不過(guò)這問(wèn)題不大。)

          說(shuō)干就干,我們把common中的模塊全部打包成mixin:

          /* common.css */

          .m-nav { ... }

          .m-news { ... }

          .m-copy_right { ... }

          改造后

          // common.scss

          @mixin m-nav {

          .m-nav { ... }

          }

          @mixin m-news {

          .m-news { ... }

          }

          @mixin m-copy_right {

          .m-copy_right { ... }

          }

          調(diào)用方式如下:

          // index.scss

          @import 'common'; // 記得先引入common

          .g-index {

          @include m-nav;

          @include m-news;

          @include m-copy_right;

          }

          原本我們會(huì)在每個(gè)需要用到公共模塊的頁(yè)面中,先引用common,然后再引用頁(yè)面css,而現(xiàn)在,我們只需要在頁(yè)面scss中直接@import common;就可以了。

          使用common:

          

          

          

          

          titleindex/title

          link rel="stylesheet" type="text/css" href="./style/common.css"/

          link rel="stylesheet" type="text/css" href="./style/index.css"/

          

          

          ...

          

          

          改造后:

          // index.scss

          @import 'common';

          

          

          

          

          titleindex/title

          link rel="stylesheet" type="text/css" href="./style/index.css"/

          

          

          ...

          

          

          很完美,

          ——至少目前為止是這樣。

          我們思考一個(gè)問(wèn)題,common除了存放模塊之外,還有沒(méi)有其他內(nèi)容?答案是肯定的,大家一定知道有個(gè)東西叫做css reset(或者normalize.css),這肯定是全局的;另外,如果是做后臺(tái)管理系統(tǒng)的話,可能還會(huì)有bootstrap。當(dāng)然,還有一些自定義的全局的樣式,比如常見(jiàn)的.clearfix,等等。

          這些東西目前我們也堆積在common當(dāng)中,而且合情合理,因?yàn)樗鼈兌际侨值臉邮健5菍?duì)比起mixin來(lái)說(shuō),這些實(shí)際內(nèi)容代碼顯得很少量,有種被淹沒(méi)的感覺(jué),使得整個(gè)common看上去就像只有mixin。但是這些實(shí)際內(nèi)容代碼的作用卻又非常重要。為了使common的構(gòu)成更加直觀,我們把mixin全部都抽離出來(lái),單獨(dú)存放一個(gè)叫做mixin.scss的文件中,然后在common引用它,這樣,mixin的管理更加的規(guī)范,而且common的結(jié)構(gòu)也更加清晰了。

          抽離mixin還有另外一個(gè)重要原因,后面會(huì)講到的,我們希望mixin作為一個(gè)純粹定義類(lèi)代碼文件,隨處可以引用而不會(huì)生成多余的代碼。

          原本我們會(huì)在每個(gè)需要用到公共模塊的頁(yè)面中,先引用common,然后再引用頁(yè)面css,而現(xiàn)在,我們只需要在頁(yè)面scss中直接@import mixin;就可以了。

          使用mixin:

          // index.scss

          @import 'common'; // 引入common,如果有需要,common里一樣可以引入mixin

          @import 'mixin'; // 引入mixin

          .g-index {

          ...

          }

          

          

          

          

          titleindex/title

          link rel="stylesheet" type="text/css" href="./style/index.css"/

          

          

          ...

          

          

          2、common.scss

          好,抽離了mixin之后,我們現(xiàn)在來(lái)重新看回common,common里應(yīng)該是些什么樣的內(nèi)容。上面的內(nèi)容我們稍稍提到了一點(diǎn),我們來(lái)展開(kāi)一下。

          2.1、css reset(normalize)

          我們知道瀏覽器千差萬(wàn)別,各瀏覽器的默認(rèn)樣式也是不盡相同,最常見(jiàn)的比如body的默認(rèn)內(nèi)邊距,p標(biāo)簽的默認(rèn)內(nèi)邊距,以及ul/ol等等。這些不統(tǒng)一的默認(rèn)樣式經(jīng)常讓我們感到頭疼,所以就有人提出一開(kāi)始寫(xiě)樣式就先把它們消除的想法,于是就催生了后來(lái)非常流行的reset.css。

          起初的reset.css很簡(jiǎn)單,大概是這樣的:

          html, body, h1, h2, h3, h4, h5, h6, p, dl, dt, dd, ul, ol, li, p {

          margin: 0;

          padding: 0;

          }

          沒(méi)錯(cuò),就是把幾乎所有會(huì)用到的標(biāo)簽都給去了內(nèi)邊距和外邊距,簡(jiǎn)單粗暴,這樣所有的標(biāo)簽就都統(tǒng)一了,而且在不同的瀏覽器下也是統(tǒng)一的。

          其他的部分每個(gè)人有各自的補(bǔ)充,比如有人會(huì)把h1~h6的所有字號(hào)給定義一遍,以保證在不同瀏覽器下他們有統(tǒng)一的大小;有人會(huì)給a標(biāo)簽設(shè)置統(tǒng)一的字體顏色和hover效果,諸如此類(lèi)等等。

          很好,沒(méi)毛病。我們把這些統(tǒng)稱(chēng)為css reset,然后再統(tǒng)一封裝到一個(gè)叫做reset.css的文件中,然后每個(gè)頁(yè)面都引用。

          這種方式一直以來(lái)都挺實(shí)用,而且大家也都這么用,沒(méi)出過(guò)什么問(wèn)題。只是后來(lái)有人提出,這種方式太過(guò)粗暴(居然還心疼瀏覽器了)。。。而且會(huì)降低頁(yè)面渲染的性能,最重要的是,這使得我們?cè)驹O(shè)計(jì)出來(lái)的表達(dá)各種含義的標(biāo)簽兒們,變得毫無(wú)特點(diǎn)了。。。

          說(shuō)的好有道理,如果你家里所有人名字不一樣但是都長(zhǎng)一個(gè)樣,還有啥意思。

          于是,就出現(xiàn)了normalize.css,normalize的目的同樣是為了統(tǒng)一各個(gè)瀏覽器下各不相同的默認(rèn)樣式,不過(guò)它并不是簡(jiǎn)單粗暴地全部抹平,而是根據(jù)規(guī)范,來(lái)人為地把那些不符合規(guī)范的默認(rèn)樣式“扶正”,從而達(dá)到統(tǒng)一各個(gè)瀏覽器默認(rèn)樣式,同時(shí)保留各個(gè)標(biāo)簽原有特點(diǎn)的目的。

          我們不能說(shuō)reset與normalize這兩種思想孰好孰壞,只能說(shuō)各有各的特點(diǎn)和作用,它們的存在都是為了解決同樣的問(wèn)題。

          2.2、插件

          一般來(lái)說(shuō),一個(gè)ui插件都會(huì)至少包括一個(gè)css文件,像bootstrap、datepicker等等。假設(shè)我們項(xiàng)目中需要以bootstrap為基礎(chǔ)框架,實(shí)現(xiàn)快速開(kāi)發(fā),那么這時(shí)候我們就需要在項(xiàng)目中全局引入bootstrap.min.css,當(dāng)然,還有bootstrap.min.js。說(shuō)到全局暴露,我們第一時(shí)間想到的是common,沒(méi)錯(cuò),我們可以在common中引入。

          有人問(wèn),插件的.css文件怎么import?額,改一下擴(kuò)展名為.scss就可以了,scss是兼容原生css語(yǔ)法的~

          所以最終,我們的common大概是這樣子的:

          // common.scss

          @import './reset';

          @import './bootstrap.min';

          @import './mixin';

          事實(shí)上,如果我們不需要使用到 mixin.scss 中的變量和mixin的話,我們可以不引用它。

          那么我們的頁(yè)面scss應(yīng)該是這樣的:

          // index.scss

          @import './common';

          @import './mixin';

          .g-index {

          ...

          }

          干凈,整潔。

          3、mixin編寫(xiě)規(guī)范

          每添加一個(gè)新角色,我們就要及時(shí)給它設(shè)置規(guī)范,好讓它按照我們的期望工作別添亂。我們接下來(lái)來(lái)歸納一下mixin的書(shū)寫(xiě)規(guī)范。

          場(chǎng)景一:項(xiàng)目里有mixin.scss、a.scss(假設(shè)這是某個(gè)功能文件)、index.scss三個(gè)文件,mixin中定義了一個(gè)變量$fontSize: 16px;,a中定義了一個(gè)變量$color: #ccc;,我們?cè)趇ndex中同時(shí)引用這兩個(gè)文件,那么我們?cè)趇ndex中是可以直接使用$fontSize和$color這兩個(gè)變量的——我的意思是,盡管在index中我們并沒(méi)有看到這兩個(gè)變量的聲明和定義,但它們就這么存在了。

          這是好事還是壞事呢?直覺(jué)告訴我,這可能有問(wèn)題。沒(méi)錯(cuò),這是不是跟我們之前討論過(guò)的 污染 很像?只不過(guò)我們之前是引用了common之后,index什么都還沒(méi)寫(xiě)就已經(jīng)被占用了很多模塊名,而現(xiàn)在是因?yàn)橐昧似渌募加昧薸ndex的很多變量名。另外,就維護(hù)的角度來(lái)看,這也是有問(wèn)題的,如果我不事先告訴你,或者你不事先看過(guò)一遍mixin和a,你知道index中的$color是哪里來(lái)的嗎?假設(shè)我們需要字體大小,你知道去哪個(gè)文件修改嗎?另外,你怎么保證同時(shí)引用mixin與a的時(shí)候,他們之間有沒(méi)有可能存在同名的變量?那誰(shuí)覆蓋誰(shuí)呢?這些問(wèn)題看起來(lái)很小,但是當(dāng)你項(xiàng)目規(guī)模大的時(shí)候,這可能是無(wú)法挽回的災(zāi)難(嚇唬誰(shuí)呢???)。

          場(chǎng)景二:假設(shè)我們的項(xiàng)目有一個(gè)主題色,邊框、tab背景、導(dǎo)航欄背景,以及字體顏色等等,都是這個(gè)主題色,為了方便使用,不想總是用取色器去取值,于是我們?cè)趍ixin中定義了一個(gè)全局變量$color: #ff9900,然后就可以愉快地到處使用了!

          整個(gè)網(wǎng)站開(kāi)發(fā)完了,一個(gè)月后,設(shè)計(jì)師突然過(guò)來(lái)跟你說(shuō):“老板說(shuō),這個(gè)主題色要改改,有點(diǎn)土,咱們換個(gè)大紅。”,于是你一臉不情愿然而內(nèi)心卻竊喜地打開(kāi)mixin,把$color的值改成了大紅,然后得瑟地對(duì)設(shè)計(jì)師說(shuō):“幸好我早有準(zhǔn)備,搞定了,你看看吧。”,保存,打開(kāi)頁(yè)面一看,設(shè)計(jì)師和你的臉都綠了,頁(yè)面怎么這么丑,有些字原本是主題色,但背景是紅色,而現(xiàn)在一改,整塊都變成紅的,內(nèi)容都看不清了,有些邊框原本就是紅色的,但是字體是原本的主題色,然而現(xiàn)在一改,邊框跟字體都變成紅的了。

          設(shè)計(jì)師:“不不不,我只是想把背景顏色改一下。”

          你:“你不是說(shuō)改主題色嗎?那就是所有的地方啊。”

          設(shè)計(jì)師:“不用,改背景就好了。”

          你:“不行啊。。。”

          設(shè)計(jì)師:“為什么不行,不就是改個(gè)背景顏色嗎?怎么設(shè)置的就怎么改回來(lái)呀。”

          你:“不是你想的那么簡(jiǎn)單。。。”

          ……

          好吧我就是嚇唬你的,你要是特能折騰那么這些都不叫事兒。

          所以我們需要對(duì)(全局)變量進(jìn)行管理,就像我們當(dāng)初管理mixin那樣,不能想在哪里定義就在哪里定義,也不能動(dòng)不動(dòng)就修改一個(gè)全局變量:

          全局變量只在mixin中定義,其他scss文件定義的變量(無(wú)論是暴露到全局還是局部)都只看作局部變量,不在當(dāng)前文件以外的地方使用(即便是在能引用到的情況下,也避免使用);

          需要使用全局變量的地方直接import mixin;

          一般來(lái)說(shuō),定義全局變量應(yīng)該慎重,全局變量的數(shù)量應(yīng)該盡量少;

          盡可能不改動(dòng),如果需求變動(dòng),除非是對(duì)用途十分確定的情況,否則請(qǐng)新增一個(gè)全局變量來(lái)逐步替換需要修改的地方;

          不要使用太過(guò)籠統(tǒng)的名詞來(lái)作為全局變量,比如color,建議直接是用色值的描述,比如$orange: #ff9900,這使得我們?cè)诰S護(hù)上更方便擴(kuò)展,如果色值需要修改,但是又不是所有的地方都需要修改,那么我們可以新定義一個(gè)變量來(lái)擴(kuò)展它,比如$red: red。

          這些點(diǎn)說(shuō)起來(lái)都有點(diǎn)飄忽,事實(shí)上也確實(shí)很難說(shuō)明白為什么要這么做,畢竟都是經(jīng)驗(yàn)總結(jié),所以大家不妨先熟悉使用sass一段時(shí)間之后,再來(lái)細(xì)細(xì)思考這些問(wèn)題。

          注意,以上講的這些都不是死規(guī)定,在某些時(shí)候,這個(gè)規(guī)范是需要根據(jù)實(shí)際項(xiàng)目而做調(diào)整的,就比如我們之后要講到的SPA。十全十美的項(xiàng)目是不存在的,也不存在能適用所有項(xiàng)目的開(kāi)發(fā)模式,因地制宜才能更好地解決問(wèn)題。而且我們目前提到的問(wèn)題都不是致命的,致命的問(wèn)題在上一節(jié)我們制定規(guī)范的時(shí)候已經(jīng)避開(kāi)了。

          調(diào)用模塊

          問(wèn)題,在哪里調(diào)用模塊?

          答,頁(yè)面scss。

          在頁(yè)面scss中調(diào)用模塊是一個(gè)好習(xí)慣,它使得我們?cè)诿總€(gè)頁(yè)面所用到的模塊既是一致的又是互相隔離的,不像在common中直接引用模塊那樣,使得一個(gè)頁(yè)面scss還沒(méi)有內(nèi)容的時(shí)候就已經(jīng)被很多模塊名污染了。

          再提個(gè)問(wèn)題,在頁(yè)面scss的哪里調(diào)用模塊?

          例一,根類(lèi)外:

          // index.scss

          @import './common';

          @import './mixin';

          @include m-nav;

          @include m-news;

          @include m-copy_right;

          .g-index {

          ...

          }

          例二,根類(lèi)內(nèi):

          // index.scss

          @import './common';

          @import './mixin';

          .g-index {

          @include m-nav;

          @include m-news;

          @include m-copy_right;

          ...

          }

          目前為止,這兩種方式都是可以的,至于我為什么用“目前為止”這個(gè)詞,那是因?yàn)槲覀兒竺鎸⒁v到的SPA,如果用例一的方式是有問(wèn)題的。所以我比較鼓勵(lì)使用例二的方式。當(dāng)然,我說(shuō)了,目前為止例一也是沒(méi)問(wèn)題的。

          性能優(yōu)化

          目前為止,我們的模塊化工作已經(jīng)算是完成了,其實(shí)已經(jīng)可以收工了。不過(guò)我們還是可以稍微做一下優(yōu)化。

          1、緩存

          我們需要考慮一個(gè)問(wèn)題:緩存。

          緩存是我們web開(kāi)發(fā)中最常見(jiàn)的情況之一,很多時(shí)候我們都需要跟緩存打交道,特別是在做性能優(yōu)化的時(shí)候。

          一般來(lái)說(shuō),靜態(tài)資源在被加載到瀏覽器之后,瀏覽器會(huì)把它本地緩存下來(lái),以便下次請(qǐng)求同個(gè)資源的時(shí)候可以快速響應(yīng),不需要再去遠(yuǎn)程服務(wù)器加載。

          我們就css來(lái)說(shuō),假設(shè)我們按照原來(lái)的方式,使用多個(gè)link去加載reset、bootstrap、common、index這幾個(gè)文件的話,這幾個(gè)文件都會(huì)被緩存下來(lái),以使得下次再訪問(wèn)這個(gè)頁(yè)面,這個(gè)頁(yè)面的加載速度會(huì)快很多。

          如果是從index頁(yè)面跳轉(zhuǎn)到about頁(yè)面呢?你會(huì)發(fā)現(xiàn)也很快,因?yàn)閍bout頁(yè)面的全局css(reset、bootstrap、common)和index頁(yè)面是一樣的,而它們?cè)谀阍L問(wèn)index的時(shí)候,已經(jīng)加載過(guò)了,得益于緩存的作用,之后的頁(yè)面打開(kāi)都快。

          我們現(xiàn)在的方式是,一個(gè)頁(yè)面所用到的所有css文件都被合并成一個(gè),也就不存在相同的文件可以利用緩存這樣的優(yōu)勢(shì)了。

          那我們有辦法改進(jìn)嗎?有的!我們只需要把common獨(dú)立出來(lái),那么common就可以做為被緩存的公共文件了。最終我們從一個(gè)頁(yè)面只引用一個(gè)文件變成了一個(gè)頁(yè)面引用兩個(gè)文件,即common和頁(yè)面css:

          // common.scss

          @import './reset';

          @import './bootstrap.min';

          @import './mixin';

          // index.scss

          @import './mixin';

          .g-index {

          ...

          }

          注意,不同于之前,我們這里的index.scss不再引入common.scss,所以我們最終是得到了兩個(gè)css文件,而common.css是在所有頁(yè)面中通過(guò)link標(biāo)簽引入的。

          如此一來(lái),我們就實(shí)現(xiàn)了既能夠合并文件,減少請(qǐng)求數(shù),又可以利用緩存,提高加載速度。

          2、壓縮

          代碼壓縮是優(yōu)化工作中最基本的一步,css的壓縮空間是很大的,尤其是我們這種 垂直的書(shū)寫(xiě)方式 ,壓縮起來(lái)是相當(dāng)高效的。

          在sass中這很簡(jiǎn)單,sass在編譯的時(shí)候提供了幾種模式,其中的compressed模式是最高效的壓縮模式,記得在編譯打包的時(shí)候選擇compressed模式就行了。

          總結(jié)

          總的來(lái)說(shuō),預(yù)處理語(yǔ)言在使我們編程更加美好的同時(shí),也使得規(guī)范更加的完善。在css本身無(wú)法實(shí)現(xiàn)的情況下,我們通過(guò)工具來(lái)完成了模塊化開(kāi)發(fā)。

        《&.doc》
        将本文的Word文档下载到电脑,方便收藏和打印
        推荐度:
        点击下载文档

        【CSS預(yù)處理語(yǔ)言的模塊化實(shí)踐實(shí)例】相關(guān)文章:

        jquery獲取css中的選擇器用法實(shí)例講解10-05

        CSS實(shí)用教程:CSS命名10-05

        div+css必看的css重則06-27

        css 書(shū)寫(xiě)技巧 CSS 技巧教程簡(jiǎn)介07-02

        jQuery css方法動(dòng)態(tài)修改CSS屬性07-06

        css的基本語(yǔ)法07-16

        css基礎(chǔ)教程之CSS基礎(chǔ)語(yǔ)法欣賞08-22

        CSS制作教程08-11

        css屬性定位教程07-23

        CSS入門(mén)教程09-05

        在线咨询
        国产高潮无套免费视频_久久九九兔免费精品6_99精品热6080YY久久_国产91久久久久久无码
      3. <sub id="h4knl"><ol id="h4knl"></ol></sub>
        <sup id="h4knl"></sup>
          <sub id="h4knl"></sub>

          <sub id="h4knl"><ol id="h4knl"><em id="h4knl"></em></ol></sub><s id="h4knl"></s>
          1. <strong id="h4knl"></strong>

          2. 日韩国产精品区一99 | 亚洲日韩国产中文字幕 | 中文字幕一级午夜影片 | 欧美v亚洲v中文v日韩v专区 | 亚洲精品91在线播放 | 久久国产精品-国产精品99 |

            CSS預(yù)處理語(yǔ)言的模塊化實(shí)踐實(shí)例

              編寫(xiě)css是前端工作中,一項(xiàng)普通而又頻繁的勞動(dòng),由于css并不是一門(mén)語(yǔ)言,所以在程序設(shè)計(jì)上顯得有些簡(jiǎn)陋。對(duì)于小型項(xiàng)目來(lái)說(shuō),css的量還不至于龐大,問(wèn)題沒(méi)有凸顯,而如果要開(kāi)發(fā)和持續(xù)維護(hù)一個(gè)較為大型的項(xiàng)目,那就需要對(duì)css進(jìn)行管理和規(guī)范了,否則會(huì)發(fā)生不可挽回的后果。

              通過(guò)規(guī)范的約束,將css的編寫(xiě)方式進(jìn)行了優(yōu)化和改進(jìn),形成一種可持續(xù)發(fā)展的路線。但還是遺留了一些問(wèn)題:冗余。雖然我們通過(guò)定義公共模塊和私有模塊,來(lái)委婉地分擔(dān)common的體積,但common的體積還是太大了,而且從設(shè)計(jì)上考慮,我們應(yīng)該盡量多地提煉公共模塊,以便更好地實(shí)現(xiàn)復(fù)用。最理想的情況是,所有的模塊都寄存在一個(gè)公共的庫(kù)里,哪里需要用到就從庫(kù)中直接調(diào)過(guò)來(lái)。這個(gè)美好的愿望不是不可實(shí)現(xiàn)的,借助預(yù)處理語(yǔ)言,我們可以很輕易地完成這事情。

              預(yù)處理語(yǔ)言是一種類(lèi)css的語(yǔ)言,我們知道css本身不是語(yǔ)言,而預(yù)處理語(yǔ)言的誕生,就是為填補(bǔ)這一部分語(yǔ)言功能。它實(shí)現(xiàn)了變量、函數(shù)、混合的定義,以及文件的引用、合并、壓縮功能,使得css也能面向?qū)ο螅瑧?yīng)付復(fù)雜龐大的業(yè)務(wù)。

              目前流行的預(yù)處理語(yǔ)言主要有兩種:less和sass。作為學(xué)習(xí),兩者都可以入門(mén)一下,而作為工作,盡量熟悉一種。我比較常用sass,所以以下內(nèi)容都是以sass為基本語(yǔ)言做介紹,兩者在特性上有很多相似的地方,所以大家不必?fù)?dān)心實(shí)現(xiàn)上有什么千差萬(wàn)別。

              sass

              基本語(yǔ)法可以到官方網(wǎng)(英語(yǔ))或者w3cplus sass guide(中文)查看學(xué)習(xí),我們這里只簡(jiǎn)單地過(guò)一遍,講一些我們需要用到的內(nèi)容,不會(huì)面面俱到。

              sass有兩種后綴名文件:一種后綴名為sass,不使用大括號(hào)和分號(hào);另一種就是我們這里使用的scss文件,這種和我們平時(shí)寫(xiě)的css文件格式差不多,使用大括號(hào)和分號(hào)。而本教程中所說(shuō)的所有sass文件都指后綴名為scss的文件。在此也建議使用后綴名為scss的文件,以避免sass后綴名的嚴(yán)格格式要求報(bào)錯(cuò)。 ——摘自w3cplus sass guide

              1、嵌套(非常重要的特性)

              sass的嵌套包括兩種:一種是選擇器的嵌套;另一種是屬性的嵌套。我們一般說(shuō)起或用到的都是選擇器的嵌套。 ——摘自w3cplus sass guide

              選擇器嵌套 所謂選擇器嵌套指的是在一個(gè)選擇器中嵌套另一個(gè)選擇器來(lái)實(shí)現(xiàn)繼承,從而增強(qiáng)了sass文件的結(jié)構(gòu)性和可讀性。在選擇器嵌套中,可以使用&表示父元素選擇器。 ——摘自w3cplus sass guide

              // index.scss

              .g-index {

              ...

              .g-hd {

              ...

              .m-nav { ... }

              }

              .g-bd {

              ...

              .m-news { ... }

              }

              .g-ft {

              ...

              .m-copy_right { ... }

              }

              .m-dialog {

              display: none;

              &.z-active { // 留意此處&的用法

              display: block;

              }

              }

              }

              編譯后:

              /* index.css */

              .g-index { ... }

              .g-index .g-hd { ... }

              .g-index .g-hd .m-nav { ... }

              .g-index .g-bd { ... }

              .g-index .g-bd .m-news { ... }

              .g-index .g-ft { ... }

              .g-index .g-ft .m-copy_right { ... }

              .g-index .m-dialog {

              display: none;

              }

              .g-index .m-dialog.z-active { // 留意此處&的編譯結(jié)果

              display: block;

              }

              是不是爽歪歪?再也不用一遍一遍地去復(fù)制和修改一大堆的選擇器,也不需要去整理它們之間的關(guān)系,只需要嵌套一下,所有的關(guān)系就如同直接看dom一樣簡(jiǎn)單明了了!解放雙手,解放雙眼,同時(shí)還提高效率。值得留意的是,我們書(shū)寫(xiě)sass的時(shí)候,應(yīng)該盡量保持sass的嵌套順序與dom一致,注意,是嵌套順序一致,而不是層次一致,因?yàn)椴⒉皇莇om里的所有元素都需要寫(xiě)樣式。

              我們?cè)賮?lái)提一個(gè)場(chǎng)景,說(shuō)明sass的嵌套寫(xiě)法利于維護(hù),假設(shè)g-bd下原本有個(gè)模塊m-article_box,現(xiàn)在我們要把m-article_box從g-bd遷移到g-hd中(當(dāng)然這個(gè)需求有些不合理~),我們來(lái)看原始代碼:

              

              

              

              

              titleindex/title

              

              

              


              


              


              


              最新文章

              

              


              


              


              

              


              


              文章標(biāo)題

              

              

            文章簡(jiǎn)介

              

              

              

              

              


              


              1

              2

              3

              4

              

              

              

              

              

              

              

              .g-bd { ... }

              .g-bd .m-article_box { ... }

              .g-bd .m-article_box .hd { ... }

              .g-bd .m-article_box .bd { ... }

              .g-bd .m-article_box .bd .list { ... }

              .g-bd .m-article_box .bd .list .item { ... }

              .g-bd .m-article_box .bd .list .item .cover { ... }

              .g-bd .m-article_box .bd .list .item .info { ... }

              .g-bd .m-article_box .bd .list .item .info .title { ... }

              .g-bd .m-article_box .bd .list .item .info .desc { ... }

              .g-bd .m-article_box .ft { ... }

              .g-bd .m-article_box .ft .page { ... }

              .g-bd .m-article_box .ft .page .pg { ... }

              按照css的方式,我們就要把所有跟m-article_box有關(guān)的部分,從g-bd全部復(fù)制到g-hd里去。這還是在模塊的書(shū)寫(xiě)符合規(guī)范的情況下,如果這個(gè)模塊書(shū)寫(xiě)不符合規(guī)范,沒(méi)有把全部結(jié)構(gòu)都掛在m-article_box類(lèi)下,那真的就是災(zāi)難了~而現(xiàn)在使用sass的話,我們只需要把m-article_box的區(qū)塊整個(gè)從g-bd剪切到g-hd就完事了(這里為了突出修改的工作量大,我特地把整個(gè)模塊結(jié)構(gòu)都寫(xiě)全了——才不是為了湊字?jǐn)?shù)。。。):

              // 修改前

              .g-hd { ... }

              .g-bd {

              .m-article_box {

              .hd { ... }

              .bd {

              .list {

              .item {

              .cover {

              ...

              }

              .info {

              .title {

              ...

              }

              .desc {

              ...

              }

              }

              }

              }

              }

              .ft {

              .page {

              .pg { ... }

              }

              }

              }

              }

              // 修改后

              .g-hd {

              .m-article_box {

              .hd { ... }

              .bd {

              .list {

              .item {

              .cover {

              ...

              }

              .info {

              .title {

              ...

              }

              .desc {

              ...

              }

              }

              }

              }

              }

              .ft {

              .page {

              .pg { ... }

              }

              }

              }

              }

              .g-bd { ... }

              非常方便,而且不容易出錯(cuò)。

              2、變量(variable)

              咱們直接上代碼:

              // index.scss

              $fontSize: 16px;

              $grey: #ccc;

              .m-nav {

              font-size: $fontSize;

              color: $grey;

              }

              編譯結(jié)果:

              /* index.css */

              .m-nav {

              font-size: 16px;

              color: #ccc;

              }

              寫(xiě)過(guò)代碼的人都熟悉 參數(shù) 的用法吧,太簡(jiǎn)單太直白了不想說(shuō)太多,自己意會(huì)吧。

              3、函數(shù)(function)

              // pixels to rems

              @function rem($px) {

              @return $px / 640 * 16rem;

              }

              太簡(jiǎn)單了直白了不想說(shuō)太多,自己意會(huì)吧。

              4、混合(mixin)

              混合,顧名思義,就是混合的意思。。。也就是我們可以事先定義一段代碼塊,在需要使用到的地方,直接引用(include),而在引用之前,這段代碼都不會(huì)出現(xiàn)在編譯文件中,也就是不會(huì)生成任何內(nèi)容。

              這也是非常重要的一個(gè)特性!我們知道common的體積非常大,而體積大的根本原因是它存放了許許多多的模塊。我們?cè)O(shè)想一下,如果將每一個(gè)模塊都打包成mixin,那common不就減肥成功了?!多年的頑疾終于看到希望,沒(méi)有比這更讓人驚喜的了!我們這就上車(chē):

              /* common.css */

              .m-nav { ... }

              .m-news { ... }

              .m-copy_right { ... }

              改造后

              // common.scss

              @mixin m-nav {

              .m-nav { ... }

              }

              @mixin m-news {

              .m-news { ... }

              }

              @mixin m-copy_right {

              .m-copy_right { ... }

              }

              // index.scss

              .g-index {

              @include m-nav;

              @include m-news;

              @include m-copy_right;

              }

              5、import

              這個(gè)屬性很眼熟?沒(méi)錯(cuò),事實(shí)上,css本身就有這個(gè)屬性實(shí)現(xiàn),我們可以在css文件中直接使用import來(lái)引入其他文件。那么css的import和sass的import有什么區(qū)別?從含義和用法上來(lái)說(shuō),沒(méi)有區(qū)別,區(qū)別在于工作原理。css的import是阻塞的,而sass的import在編譯后,其實(shí)是合并文件,最后只產(chǎn)出一個(gè)css文件,而css則沒(méi)有合并,該多少個(gè)文件就還是多少個(gè)文件。

              注意:

              只有import一個(gè).sass/.scss文件的時(shí)候,才可以省去后綴名,如果是直接import一個(gè).css文件,要補(bǔ)全文件名;

              import之后的分號(hào);不要漏寫(xiě),會(huì)報(bào)錯(cuò);

              sass如果import的是一個(gè).css文件的話,那它的作用就跟css原生的import作用一樣,只有import一個(gè)sass文件的時(shí)候,才是合并文件。

              如下:

              // index.scss

              @import 'common';

              @import 'a.css';

              編譯結(jié)果:

              /* index.scss */

              .m-nav { ... }

              .m-news { ... }

              .m-copy_right { ... }

              @import url('a.css');

              css的import之所以沒(méi)有被普遍使用是有原因的。我們可以大概猜到它的工作原理:a.css import b.css以后,當(dāng)瀏覽器加載到頁(yè)面中的a.css的時(shí)候,已經(jīng)準(zhǔn)備按照a.css的內(nèi)容來(lái)渲染頁(yè)面了,剛解析到第一行,發(fā)現(xiàn)a.css居然還import了一個(gè)b.css,于是它不得不先放下a.css(既阻塞a.css),去加載b.css,直到b.css加載完,并且優(yōu)先解析它,然后才開(kāi)始回來(lái)解析a.css——鬼知道b.css會(huì)不會(huì)又import了c.css……這直接導(dǎo)致了渲染工作滯后,引發(fā)性能問(wèn)題。

              說(shuō)實(shí)話我還不如直接用兩個(gè)link標(biāo)簽去同步加載a.css和b.css,效率會(huì)高一些。

              所以css的import基本是被拋棄了的屬性。

              sass的import主要的好處就是把文件合并了,減少了請(qǐng)求。原本需要link好幾個(gè)css文件的頁(yè)面,現(xiàn)在只需要一個(gè)。

              模塊化

              終于要開(kāi)始干點(diǎn)正事了,首先我們來(lái)回顧一下,上一節(jié)我們以規(guī)范為基礎(chǔ)構(gòu)建的模塊化項(xiàng)目,遺留了一些什么問(wèn)題。

              冗余 體積龐大的common;

              使用cm-模塊區(qū)別m-模塊,使得后期開(kāi)發(fā)過(guò)程中,m-模塊向cm-模塊轉(zhuǎn)變過(guò)程比較繁瑣;

              ……

              好像,問(wèn)題也不是特別多,我們一個(gè)一個(gè)解決。

              為了方便,在這里我們把每個(gè)頁(yè)面所對(duì)應(yīng)的scss文件叫做 頁(yè)面scss;把變量、函數(shù)、混合等(沒(méi)有被引用或者執(zhí)行的情況下)編譯后不產(chǎn)生實(shí)際內(nèi)容的代碼叫做 定義類(lèi)代碼 ,那么相對(duì)應(yīng)的其他內(nèi)容就是 實(shí)際內(nèi)容代碼。

              1、mixin.scss

              我們知道,一方面,在common中過(guò)多地添加模塊最終會(huì)導(dǎo)致common的體積過(guò)大,使得資源冗余,另一方面,為了方便維護(hù),我們又希望盡量多地把模塊公有化。

              這是一對(duì)矛盾,僅靠css本身是無(wú)法解決的,但sass可以!如果我們使用mixin來(lái)代替直接書(shū)寫(xiě)模塊,由于mixin并不直接生成代碼,而是通過(guò)主動(dòng)引用,才能生成對(duì)應(yīng)內(nèi)容,那么理論上,common就可以無(wú)限多地存放模塊而不必占用一點(diǎn)空間!

              (注意,這里說(shuō)的是理論上,實(shí)際應(yīng)用中,文件太過(guò)龐大的話,免不了還是要受到命名沖突的限制的,不過(guò)這問(wèn)題不大。)

              說(shuō)干就干,我們把common中的模塊全部打包成mixin:

              /* common.css */

              .m-nav { ... }

              .m-news { ... }

              .m-copy_right { ... }

              改造后

              // common.scss

              @mixin m-nav {

              .m-nav { ... }

              }

              @mixin m-news {

              .m-news { ... }

              }

              @mixin m-copy_right {

              .m-copy_right { ... }

              }

              調(diào)用方式如下:

              // index.scss

              @import 'common'; // 記得先引入common

              .g-index {

              @include m-nav;

              @include m-news;

              @include m-copy_right;

              }

              原本我們會(huì)在每個(gè)需要用到公共模塊的頁(yè)面中,先引用common,然后再引用頁(yè)面css,而現(xiàn)在,我們只需要在頁(yè)面scss中直接@import common;就可以了。

              使用common:

              

              

              

              

              titleindex/title

              link rel="stylesheet" type="text/css" href="./style/common.css"/

              link rel="stylesheet" type="text/css" href="./style/index.css"/

              

              

              ...

              

              

              改造后:

              // index.scss

              @import 'common';

              

              

              

              

              titleindex/title

              link rel="stylesheet" type="text/css" href="./style/index.css"/

              

              

              ...

              

              

              很完美,

              ——至少目前為止是這樣。

              我們思考一個(gè)問(wèn)題,common除了存放模塊之外,還有沒(méi)有其他內(nèi)容?答案是肯定的,大家一定知道有個(gè)東西叫做css reset(或者normalize.css),這肯定是全局的;另外,如果是做后臺(tái)管理系統(tǒng)的話,可能還會(huì)有bootstrap。當(dāng)然,還有一些自定義的全局的樣式,比如常見(jiàn)的.clearfix,等等。

              這些東西目前我們也堆積在common當(dāng)中,而且合情合理,因?yàn)樗鼈兌际侨值臉邮健5菍?duì)比起mixin來(lái)說(shuō),這些實(shí)際內(nèi)容代碼顯得很少量,有種被淹沒(méi)的感覺(jué),使得整個(gè)common看上去就像只有mixin。但是這些實(shí)際內(nèi)容代碼的作用卻又非常重要。為了使common的構(gòu)成更加直觀,我們把mixin全部都抽離出來(lái),單獨(dú)存放一個(gè)叫做mixin.scss的文件中,然后在common引用它,這樣,mixin的管理更加的規(guī)范,而且common的結(jié)構(gòu)也更加清晰了。

              抽離mixin還有另外一個(gè)重要原因,后面會(huì)講到的,我們希望mixin作為一個(gè)純粹定義類(lèi)代碼文件,隨處可以引用而不會(huì)生成多余的代碼。

              原本我們會(huì)在每個(gè)需要用到公共模塊的頁(yè)面中,先引用common,然后再引用頁(yè)面css,而現(xiàn)在,我們只需要在頁(yè)面scss中直接@import mixin;就可以了。

              使用mixin:

              // index.scss

              @import 'common'; // 引入common,如果有需要,common里一樣可以引入mixin

              @import 'mixin'; // 引入mixin

              .g-index {

              ...

              }

              

              

              

              

              titleindex/title

              link rel="stylesheet" type="text/css" href="./style/index.css"/

              

              

              ...

              

              

              2、common.scss

              好,抽離了mixin之后,我們現(xiàn)在來(lái)重新看回common,common里應(yīng)該是些什么樣的內(nèi)容。上面的內(nèi)容我們稍稍提到了一點(diǎn),我們來(lái)展開(kāi)一下。

              2.1、css reset(normalize)

              我們知道瀏覽器千差萬(wàn)別,各瀏覽器的默認(rèn)樣式也是不盡相同,最常見(jiàn)的比如body的默認(rèn)內(nèi)邊距,p標(biāo)簽的默認(rèn)內(nèi)邊距,以及ul/ol等等。這些不統(tǒng)一的默認(rèn)樣式經(jīng)常讓我們感到頭疼,所以就有人提出一開(kāi)始寫(xiě)樣式就先把它們消除的想法,于是就催生了后來(lái)非常流行的reset.css。

              起初的reset.css很簡(jiǎn)單,大概是這樣的:

              html, body, h1, h2, h3, h4, h5, h6, p, dl, dt, dd, ul, ol, li, p {

              margin: 0;

              padding: 0;

              }

              沒(méi)錯(cuò),就是把幾乎所有會(huì)用到的標(biāo)簽都給去了內(nèi)邊距和外邊距,簡(jiǎn)單粗暴,這樣所有的標(biāo)簽就都統(tǒng)一了,而且在不同的瀏覽器下也是統(tǒng)一的。

              其他的部分每個(gè)人有各自的補(bǔ)充,比如有人會(huì)把h1~h6的所有字號(hào)給定義一遍,以保證在不同瀏覽器下他們有統(tǒng)一的大小;有人會(huì)給a標(biāo)簽設(shè)置統(tǒng)一的字體顏色和hover效果,諸如此類(lèi)等等。

              很好,沒(méi)毛病。我們把這些統(tǒng)稱(chēng)為css reset,然后再統(tǒng)一封裝到一個(gè)叫做reset.css的文件中,然后每個(gè)頁(yè)面都引用。

              這種方式一直以來(lái)都挺實(shí)用,而且大家也都這么用,沒(méi)出過(guò)什么問(wèn)題。只是后來(lái)有人提出,這種方式太過(guò)粗暴(居然還心疼瀏覽器了)。。。而且會(huì)降低頁(yè)面渲染的性能,最重要的是,這使得我們?cè)驹O(shè)計(jì)出來(lái)的表達(dá)各種含義的標(biāo)簽兒們,變得毫無(wú)特點(diǎn)了。。。

              說(shuō)的好有道理,如果你家里所有人名字不一樣但是都長(zhǎng)一個(gè)樣,還有啥意思。

              于是,就出現(xiàn)了normalize.css,normalize的目的同樣是為了統(tǒng)一各個(gè)瀏覽器下各不相同的默認(rèn)樣式,不過(guò)它并不是簡(jiǎn)單粗暴地全部抹平,而是根據(jù)規(guī)范,來(lái)人為地把那些不符合規(guī)范的默認(rèn)樣式“扶正”,從而達(dá)到統(tǒng)一各個(gè)瀏覽器默認(rèn)樣式,同時(shí)保留各個(gè)標(biāo)簽原有特點(diǎn)的目的。

              我們不能說(shuō)reset與normalize這兩種思想孰好孰壞,只能說(shuō)各有各的特點(diǎn)和作用,它們的存在都是為了解決同樣的問(wèn)題。

              2.2、插件

              一般來(lái)說(shuō),一個(gè)ui插件都會(huì)至少包括一個(gè)css文件,像bootstrap、datepicker等等。假設(shè)我們項(xiàng)目中需要以bootstrap為基礎(chǔ)框架,實(shí)現(xiàn)快速開(kāi)發(fā),那么這時(shí)候我們就需要在項(xiàng)目中全局引入bootstrap.min.css,當(dāng)然,還有bootstrap.min.js。說(shuō)到全局暴露,我們第一時(shí)間想到的是common,沒(méi)錯(cuò),我們可以在common中引入。

              有人問(wèn),插件的.css文件怎么import?額,改一下擴(kuò)展名為.scss就可以了,scss是兼容原生css語(yǔ)法的~

              所以最終,我們的common大概是這樣子的:

              // common.scss

              @import './reset';

              @import './bootstrap.min';

              @import './mixin';

              事實(shí)上,如果我們不需要使用到 mixin.scss 中的變量和mixin的話,我們可以不引用它。

              那么我們的頁(yè)面scss應(yīng)該是這樣的:

              // index.scss

              @import './common';

              @import './mixin';

              .g-index {

              ...

              }

              干凈,整潔。

              3、mixin編寫(xiě)規(guī)范

              每添加一個(gè)新角色,我們就要及時(shí)給它設(shè)置規(guī)范,好讓它按照我們的期望工作別添亂。我們接下來(lái)來(lái)歸納一下mixin的書(shū)寫(xiě)規(guī)范。

              場(chǎng)景一:項(xiàng)目里有mixin.scss、a.scss(假設(shè)這是某個(gè)功能文件)、index.scss三個(gè)文件,mixin中定義了一個(gè)變量$fontSize: 16px;,a中定義了一個(gè)變量$color: #ccc;,我們?cè)趇ndex中同時(shí)引用這兩個(gè)文件,那么我們?cè)趇ndex中是可以直接使用$fontSize和$color這兩個(gè)變量的——我的意思是,盡管在index中我們并沒(méi)有看到這兩個(gè)變量的聲明和定義,但它們就這么存在了。

              這是好事還是壞事呢?直覺(jué)告訴我,這可能有問(wèn)題。沒(méi)錯(cuò),這是不是跟我們之前討論過(guò)的 污染 很像?只不過(guò)我們之前是引用了common之后,index什么都還沒(méi)寫(xiě)就已經(jīng)被占用了很多模塊名,而現(xiàn)在是因?yàn)橐昧似渌募加昧薸ndex的很多變量名。另外,就維護(hù)的角度來(lái)看,這也是有問(wèn)題的,如果我不事先告訴你,或者你不事先看過(guò)一遍mixin和a,你知道index中的$color是哪里來(lái)的嗎?假設(shè)我們需要字體大小,你知道去哪個(gè)文件修改嗎?另外,你怎么保證同時(shí)引用mixin與a的時(shí)候,他們之間有沒(méi)有可能存在同名的變量?那誰(shuí)覆蓋誰(shuí)呢?這些問(wèn)題看起來(lái)很小,但是當(dāng)你項(xiàng)目規(guī)模大的時(shí)候,這可能是無(wú)法挽回的災(zāi)難(嚇唬誰(shuí)呢???)。

              場(chǎng)景二:假設(shè)我們的項(xiàng)目有一個(gè)主題色,邊框、tab背景、導(dǎo)航欄背景,以及字體顏色等等,都是這個(gè)主題色,為了方便使用,不想總是用取色器去取值,于是我們?cè)趍ixin中定義了一個(gè)全局變量$color: #ff9900,然后就可以愉快地到處使用了!

              整個(gè)網(wǎng)站開(kāi)發(fā)完了,一個(gè)月后,設(shè)計(jì)師突然過(guò)來(lái)跟你說(shuō):“老板說(shuō),這個(gè)主題色要改改,有點(diǎn)土,咱們換個(gè)大紅。”,于是你一臉不情愿然而內(nèi)心卻竊喜地打開(kāi)mixin,把$color的值改成了大紅,然后得瑟地對(duì)設(shè)計(jì)師說(shuō):“幸好我早有準(zhǔn)備,搞定了,你看看吧。”,保存,打開(kāi)頁(yè)面一看,設(shè)計(jì)師和你的臉都綠了,頁(yè)面怎么這么丑,有些字原本是主題色,但背景是紅色,而現(xiàn)在一改,整塊都變成紅的,內(nèi)容都看不清了,有些邊框原本就是紅色的,但是字體是原本的主題色,然而現(xiàn)在一改,邊框跟字體都變成紅的了。

              設(shè)計(jì)師:“不不不,我只是想把背景顏色改一下。”

              你:“你不是說(shuō)改主題色嗎?那就是所有的地方啊。”

              設(shè)計(jì)師:“不用,改背景就好了。”

              你:“不行啊。。。”

              設(shè)計(jì)師:“為什么不行,不就是改個(gè)背景顏色嗎?怎么設(shè)置的就怎么改回來(lái)呀。”

              你:“不是你想的那么簡(jiǎn)單。。。”

              ……

              好吧我就是嚇唬你的,你要是特能折騰那么這些都不叫事兒。

              所以我們需要對(duì)(全局)變量進(jìn)行管理,就像我們當(dāng)初管理mixin那樣,不能想在哪里定義就在哪里定義,也不能動(dòng)不動(dòng)就修改一個(gè)全局變量:

              全局變量只在mixin中定義,其他scss文件定義的變量(無(wú)論是暴露到全局還是局部)都只看作局部變量,不在當(dāng)前文件以外的地方使用(即便是在能引用到的情況下,也避免使用);

              需要使用全局變量的地方直接import mixin;

              一般來(lái)說(shuō),定義全局變量應(yīng)該慎重,全局變量的數(shù)量應(yīng)該盡量少;

              盡可能不改動(dòng),如果需求變動(dòng),除非是對(duì)用途十分確定的情況,否則請(qǐng)新增一個(gè)全局變量來(lái)逐步替換需要修改的地方;

              不要使用太過(guò)籠統(tǒng)的名詞來(lái)作為全局變量,比如color,建議直接是用色值的描述,比如$orange: #ff9900,這使得我們?cè)诰S護(hù)上更方便擴(kuò)展,如果色值需要修改,但是又不是所有的地方都需要修改,那么我們可以新定義一個(gè)變量來(lái)擴(kuò)展它,比如$red: red。

              這些點(diǎn)說(shuō)起來(lái)都有點(diǎn)飄忽,事實(shí)上也確實(shí)很難說(shuō)明白為什么要這么做,畢竟都是經(jīng)驗(yàn)總結(jié),所以大家不妨先熟悉使用sass一段時(shí)間之后,再來(lái)細(xì)細(xì)思考這些問(wèn)題。

              注意,以上講的這些都不是死規(guī)定,在某些時(shí)候,這個(gè)規(guī)范是需要根據(jù)實(shí)際項(xiàng)目而做調(diào)整的,就比如我們之后要講到的SPA。十全十美的項(xiàng)目是不存在的,也不存在能適用所有項(xiàng)目的開(kāi)發(fā)模式,因地制宜才能更好地解決問(wèn)題。而且我們目前提到的問(wèn)題都不是致命的,致命的問(wèn)題在上一節(jié)我們制定規(guī)范的時(shí)候已經(jīng)避開(kāi)了。

              調(diào)用模塊

              問(wèn)題,在哪里調(diào)用模塊?

              答,頁(yè)面scss。

              在頁(yè)面scss中調(diào)用模塊是一個(gè)好習(xí)慣,它使得我們?cè)诿總€(gè)頁(yè)面所用到的模塊既是一致的又是互相隔離的,不像在common中直接引用模塊那樣,使得一個(gè)頁(yè)面scss還沒(méi)有內(nèi)容的時(shí)候就已經(jīng)被很多模塊名污染了。

              再提個(gè)問(wèn)題,在頁(yè)面scss的哪里調(diào)用模塊?

              例一,根類(lèi)外:

              // index.scss

              @import './common';

              @import './mixin';

              @include m-nav;

              @include m-news;

              @include m-copy_right;

              .g-index {

              ...

              }

              例二,根類(lèi)內(nèi):

              // index.scss

              @import './common';

              @import './mixin';

              .g-index {

              @include m-nav;

              @include m-news;

              @include m-copy_right;

              ...

              }

              目前為止,這兩種方式都是可以的,至于我為什么用“目前為止”這個(gè)詞,那是因?yàn)槲覀兒竺鎸⒁v到的SPA,如果用例一的方式是有問(wèn)題的。所以我比較鼓勵(lì)使用例二的方式。當(dāng)然,我說(shuō)了,目前為止例一也是沒(méi)問(wèn)題的。

              性能優(yōu)化

              目前為止,我們的模塊化工作已經(jīng)算是完成了,其實(shí)已經(jīng)可以收工了。不過(guò)我們還是可以稍微做一下優(yōu)化。

              1、緩存

              我們需要考慮一個(gè)問(wèn)題:緩存。

              緩存是我們web開(kāi)發(fā)中最常見(jiàn)的情況之一,很多時(shí)候我們都需要跟緩存打交道,特別是在做性能優(yōu)化的時(shí)候。

              一般來(lái)說(shuō),靜態(tài)資源在被加載到瀏覽器之后,瀏覽器會(huì)把它本地緩存下來(lái),以便下次請(qǐng)求同個(gè)資源的時(shí)候可以快速響應(yīng),不需要再去遠(yuǎn)程服務(wù)器加載。

              我們就css來(lái)說(shuō),假設(shè)我們按照原來(lái)的方式,使用多個(gè)link去加載reset、bootstrap、common、index這幾個(gè)文件的話,這幾個(gè)文件都會(huì)被緩存下來(lái),以使得下次再訪問(wèn)這個(gè)頁(yè)面,這個(gè)頁(yè)面的加載速度會(huì)快很多。

              如果是從index頁(yè)面跳轉(zhuǎn)到about頁(yè)面呢?你會(huì)發(fā)現(xiàn)也很快,因?yàn)閍bout頁(yè)面的全局css(reset、bootstrap、common)和index頁(yè)面是一樣的,而它們?cè)谀阍L問(wèn)index的時(shí)候,已經(jīng)加載過(guò)了,得益于緩存的作用,之后的頁(yè)面打開(kāi)都快。

              我們現(xiàn)在的方式是,一個(gè)頁(yè)面所用到的所有css文件都被合并成一個(gè),也就不存在相同的文件可以利用緩存這樣的優(yōu)勢(shì)了。

              那我們有辦法改進(jìn)嗎?有的!我們只需要把common獨(dú)立出來(lái),那么common就可以做為被緩存的公共文件了。最終我們從一個(gè)頁(yè)面只引用一個(gè)文件變成了一個(gè)頁(yè)面引用兩個(gè)文件,即common和頁(yè)面css:

              // common.scss

              @import './reset';

              @import './bootstrap.min';

              @import './mixin';

              // index.scss

              @import './mixin';

              .g-index {

              ...

              }

              注意,不同于之前,我們這里的index.scss不再引入common.scss,所以我們最終是得到了兩個(gè)css文件,而common.css是在所有頁(yè)面中通過(guò)link標(biāo)簽引入的。

              如此一來(lái),我們就實(shí)現(xiàn)了既能夠合并文件,減少請(qǐng)求數(shù),又可以利用緩存,提高加載速度。

              2、壓縮

              代碼壓縮是優(yōu)化工作中最基本的一步,css的壓縮空間是很大的,尤其是我們這種 垂直的書(shū)寫(xiě)方式 ,壓縮起來(lái)是相當(dāng)高效的。

              在sass中這很簡(jiǎn)單,sass在編譯的時(shí)候提供了幾種模式,其中的compressed模式是最高效的壓縮模式,記得在編譯打包的時(shí)候選擇compressed模式就行了。

              總結(jié)

              總的來(lái)說(shuō),預(yù)處理語(yǔ)言在使我們編程更加美好的同時(shí),也使得規(guī)范更加的完善。在css本身無(wú)法實(shí)現(xiàn)的情況下,我們通過(guò)工具來(lái)完成了模塊化開(kāi)發(fā)。