<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>

您好,歡迎來電子發燒友網! ,新用戶?[免費注冊]

您的位置:電子發燒友網>源碼下載>集成開發環境源碼>

CSS工程化實踐成果分析

大?。?/span>1.6 MB 人氣: 2017-09-27 需要積分:1

  作為Web開發的重要組成部分,CSS技術演進也在推動著前端工程化不斷進步。本文將從CSS模塊化、namespace約束、CSS in JS方案三個方面逐步深入解讀CSS在工程化領域取得的成果。

  CSS技術的演進

  CSS是Web開發中不可或缺的一部分,在前端工程化不斷進步的今天,一方面CSS特性隨著規范的升級越來越豐富,另一方面,前端業務復雜性的增加帶來的工程愈加龐大, 驅使著開發者不斷尋找CSS工程化的最佳實踐。

  Web開發模塊化趨勢

  不可否認, 無論從現代前端框架(React、 Vue、Angular、 Polymer等), 還是從W3C的Web Components草案來看,組件化已經是前端開發的主流之選和未來的發展方向,正如在Reddit上有網友說道“Facebook.com’s codebase includes over 20,000 components”。 廣義上看,所有頁面上都可以被劃分成一個個組件,相對于過去以網頁作為開發單位,以組件為單位開發有著可復用、可擴展等一系列有利于項目工程化的優點。

  在這種組件化趨勢的背景下,CSS模塊化也漸漸有著各種嘗試。

  預處理與后處理

  預處理

  比較流行的CSS預處理器Sass、Less和Stylus,CSS預處理器的出現主要因CSS缺少編程語言的靈活性而生,是引入了一些編程概念而生的DSL,開發者編寫簡潔的語義化DSL代碼,由預處理器編譯成CSS。

  以Sass為例,該預處理器支持.scss、.sass文件類型,其語法支持變量、選擇器嵌套、繼承(extend)、混合(mixin)和一些邏輯語句,同時還支持跨文件的導入功能,因而使得開發者能夠很好地使用編程思想書寫樣式。

  從實際使用情況來看,幾個預處理器各有優缺點,從社區活躍度上看Sass》Less》Stylus。Sass是三個中間最早也是最成熟的,因而有著很多開源積累和很好編程范式,像內置了很多Sass函數的Compass框架,就是很好的一個例子。Less相對于Sass的優點在于十分的輕量,也完全兼容CSS,但另一方面可編程能力不如Sass,Bootstrap最新版本的CSS預處理器也從Less換成Sass。Stylus來源于Node社區,使用體驗上并不輸給Sass和Less,無論是編譯速度還是語法范式,個人看來,Stylus在某種程度上更加優于其他兩個。

  后處理

  后處理器是對原生CSS進行處理并最終生成CSS的處理器,廣義上還是個預處理器,與上面提到的預處理器不同的是,它處理的對象是標準CSS(如圖1所示),比較典型的后處理工具有以下幾種。

  clean-css:壓縮CSS

  AutoPrefixer:自動添加CSS3屬性各瀏覽器的前綴

  Rework:取代Stylus的插件化框架

  PostCSS

  PostCSS

  PostCSS最初是從AutoPrefixer項目中抽象出來的框架,它本身并不對CSS做具體的業務操作,只是將CSS解析成抽象語法樹(AST),樣式的操作由之后運行的插件系統完成(如圖2所示)。正如其本身所言Transforming styles with JS plugins”。

  更多時候我們在討論PostCSS的時候,并不止停留在它是解析CSS的核心工具,更包括它創建的插件系統,而今PostCSS最為吸引開發者的正是其擴展性較強的插件系統和豐富的插件支持。

  常用的插件有:

  Autoprefixer:自動補全CSS屬性兼容性前綴

  postcss-cssnext:使用最新的CSS語法

  postcss-modules:組件內自動關聯樣式至選擇器

  Stylelint:CSS語法檢查器等

  如果已有的插件不能滿足現有的需求,完全可以手寫一個插件:

  // 官方示例rem轉pxvarcustom = function(css, opts){css.eachDecl( function(decl){decl.value = decl.value.replace( /\d+rem/, function(str){return16* parseFloat(str) + “px”; }); }); };

  當然,PostCSS的解析并不局限于CSS,結合它提供的自定義語法解析接口,完全可以定義自己的語法。其實類似于postcss-scss的插件社區已經有很多了,使用這些插件,可以將原來基于Sass、Less等預處理器的代碼遷移至PostCSS。相對于傳統的預處理器,PostCSS這種開放平臺型的體系,不拘束開發者的開發方式,同時也促進了更多對于CSS解決方案的探索。

  回過頭來看,為什么會有CSS預處理操作后的處理操作?其實主要的原因在于前端項目的膨脹使得用傳統手工編寫并維護CSS變得很不堪,根本原因則是CSS缺少編程語言特性,要做到CSS代碼的模塊化以及高復用的抽象處理,就必須引入一些編程的思想。相對于Java標準推進以及基礎設施的完備,CSS在編程方面的探索更多來自于社區,也并無統一的事實標準,這也是CSS發展落后于Java的原因。

  namespace約束

  一方面我們需要關注技術能夠帶來代碼上的模塊化,另一方面我們又要思考如何使用一個良好的風格架構起項目中的CSS。CSS除了代碼外,另一個很重要的就是CSS選擇標記。而CSS選擇器的命名空間是全局的,并沒有局部的概念,因而如何利用好這個全局的空間,選擇良好的結構風格,也是在開發過程中必須考慮的。

  OOCSS

  OOCS(Object-Oriented CSS)即面向對象CSS,主要有兩個核心原則。

  分離結構和皮膚(Separate Structure and Skin)

  皮膚即一些重復的視覺特征,如邊框、背景、顏色,分離是為了更多的復用;結構是指元素大小特征,如高度、寬度、邊距等等。

  .button{ padding:10px; box-shadow:rgba(0, 0, 0, .5)2px 2px 5px; }.widget{ overflow:auto;box-shadow:rgba(0, 0, 0, .5)2px 2px 5px; }

  根據此原則,我們需要對公用的皮膚進行提取并分離,如下。

  .button{ padding:10px; }.widget{ overflow:auto; }.skin{ box-shadow:rgba(0, 0, 0, .5)2px 2px5px; }

  分離容器和內容(Separate Container an Content)

  打破容器內元素對于容器的依賴,元素樣式應該獨立存在。如下面示例。

  《divclass=“container”》《h2》xxx 《/h2》《/div》.container h2 { 。。.}

  上面的h2元素依賴于父元素container,對應此原則,h2元素需要使用一個單獨的選擇器,如下。

  《divclass=“container”》《h2class=“category”》xxx 《/h2》《/div》.category { 。。.}

  從實踐中看出,使用OOSCC范式,遵守了DRY的原則,能夠大量減少重復的樣式代碼,提高代碼復用;同時,視覺元素可以靈活組合各個類名,展示不同的效果,豐富的類名也同時使得元素有著更好的可讀性;另一方面,由于容器和內容的分離,CSS完成了與HTML結構解耦。

  但同時也會帶來一些缺點,抽象復用會使class越來越多,極端情況下可能會產生很多原子類,這對于那些偏向于“單一來源原則”的開發者來說并不受歡迎。

  SMACSS

  SMACSS(Scalable and Modular Architecture for CSS)即模塊化架構的可擴展CSS,它主要將規則分為五類。

  基礎(Base)

  tag select的樣式, 定義最基礎全局樣式, 如CSS REST。

  html, body, form{ margin:0; padding:0; }a{ color:#039; }a:hover{ color:#03C; }

  布局(Layout)

  將頁面分為各個區域的元素塊。

  .header{}。。.。 .footer{}

  模塊(Module)

  可復用的單元。在模塊中,需要注意的是選擇器一律選擇class selector,避免嵌套子選擇器,減少權重, 方便外部覆蓋。

  《div class= “pod pod-constrained”》 。。.《/ div》 《div class= “pod pod-callout”》 。。.《/div》 .pod{width:100%; }.pod.pod-callout{ width:200px; }.pod.pod-constrained{}

  狀態(State)

  狀態class一般通過Java動態掛載到元素上,可以根據狀態覆蓋元素上特定屬性。

  .tab { background-color: purple; 。。.} .is-tab-active { background-color:white; }

  主題(Theme)

  可選的視覺外觀。一般根據需求有顏色、字體、布局等等,實現是將這些樣式單獨抽出來,根據外部條件(data屬性、媒體查詢等)動態設置。

  SMACSS的主要優點在于按照不同的業務邏輯,將整個CSS結構化分更加細致,約束好命名,最小化深度,在編寫的時候,使用SMACSS規范能夠更好地組織CSS文件結構和class命名。

  BEM

  BEM即Block Element Modifier,類名命名規則為Block__Element–Modifier。

  Block所屬組件名稱

  Element組件內元素名稱

  Modifier元素或組件修飾符

  其核心思想就是組件化。首先一個頁面可以按層級依次劃分出多個組件,其次就是單獨標記這些元素。BEM通過簡單的塊、元素、修飾符的約束規則確保類名的唯一,同時將類選擇器的語義化提升了一個新的高度。

  《form class= “form form--theme-xmas form--simple”》 《input class=“form__input”type=“text”/》 《input class= “form__submit form__submit--disabled”type=“submit”/》 《/form》 .form{ }.form--theme-xmas{ }.form--simple{}.form__input{ }.form__submit{ }.form__submit--disabled{ }

  BEM通過簡單的命名規則使得關聯類名元素語義性、可讀性更強,有利于項目管理和多人協作。同時BEM方案中并沒有嵌套,所有類名最淺深度,并不會出現嵌套過深難以覆蓋的情況,易于維護、復用。

  另一方面,BEM強調單一職責原則和單一樣式來源原則,意味著傳統純手工CSS可能會產生大量重復的代碼,但是結合各種CSS預處理和PostCSS就可以很好避免問題的產生。另外,雖說原則簡單,但在實際使用中,維護BEM的命名確實需要一些成本,很多時候命名反而成了一件難事。

  CSS in JS

  CSS in JS方案一開始是由Facebook工程師Vjeux在一次分享中提出的,針對CSS在React開發中遇到的各種問題,隨后社區涌現了各樣方案。

  雖然以上模塊化的命名約定可以解決風格上的問題,但正如上文而言,也引入一些成本。而對于一些高復用的組件,使用以上高度語義化的方案是個很好的選擇,這種成本是必需的,但對于沒有復用的業務組件來說,顯然這種命名的成本大于收益,特別是在多人協作時候。另外,面對現代前端框架的發展,純靠CSS方案并不能很好地解決。

  CSS Modlue

  CSS Module不同于Vjeux完全放棄CSS的做法,它只是選擇了用Java來管理樣式與元素的關聯,CSS Module為每個本地定義的類名動態創建一個全局唯一類名,然后注入到UI上,實現編寫樣式規則的局部模塊化。

  css-loader內置支持CSS Module, 只需設置下查詢參數, 即可在Java中使用CSS文件的導入。

  { loader:‘css-loader’, query: { module: true, localInentName: ‘[name]__[local]--[hash:base64:5]’// } }

  在Java中導入CSS文件,最終得到的其實是一個CSS文件經過parse后生成的類名映射對象{[localName]: [hashed-Name], …。}。

  // Header.jsx import style from ‘。/Header.css’。。.console.log(style)//{header:‘Header__header--3kSIq_0’} export default () =》 《div className={style.header}》《/div》

  同時CSS文件也會被編譯成對應的類名。

  .Header__header-- 3kSIq_0- {} // from Header .css.header{}

  從開發體驗上看,CSS-Module這種做法讓開發者不必在類名的命名上小心翼翼,直接使用隨機編譯生成唯一標識,讓類名成為局部變量成為了可能。但同時也因為隨機性,失去了通過此局部類名實現樣式覆蓋的可能性,覆蓋時不得不考慮使用其他選擇器(如屬性選擇器)。對于復用的組件而言,靈活性是必不可少的,這種局部模塊化方案并不適合這種高度抽象復用的組件,而對于一次性業務組件確實能夠提升開發效率。

  同時CSS Module還支持使用composes實現CSS代碼的組合復用。

  /* button.css */ .base{} .normal { composes: base 。。.} // button.jsx import style from‘。/button.css’export default () =》 《button className={style.normal}》按按《/button》// 《button class= “button__base--180HZ_0 button__normal--x38Eh_0”》按按《/button》

  當然CSS Module還可以配合各種預處理器一起使用,只需在css-loader之前添加對應的loader,但在編寫的時候要注意CSS Module的語法要在處理器之后合法。實際使用中,對于CSS代碼的解耦,如果引入了預處理器,代碼文件的模塊化就不建議使用composes來解決。

  styled-components

  styled-components也是一個完全的CSS in JS方案,先看語法。

  // buttonimport styled from‘styled-compenents’constButton = styled.button` padding: 10px; ${props =》 props.primary ? ‘palevioletred’: ‘white’}; ` 《Button》按鈕 《/Button》《Buttonprimary》按鈕 《/Button》

  其編譯后也是如同CSS-in-module一樣,隨機混淆生成全局唯一類名,對應生成CSS文件。styledcomponent的核心是“樣式即組件”,將字符串解析成CSS,并創建對應該樣式的JSX元素,它有著Java強大的編程能力,完全可以勝任,同時讓組件樣式與組件邏輯耦合在一起,真正做到組件緊耦合少依賴。當然有些開發不喜歡這種耦合,也完全可以將樣式組件和邏輯組件分離,而在Java中分離代碼本身也是件易事。

  當然,styled-components真正的應用并不僅僅如此,它完全是一個完備的樣式解決方案,有著如擴展、主題、服務端渲染、Babel插件、ReactNative等一系列支持,也深受一些開發者歡迎。這里比較有趣的是看似奇怪的語法形式, 其實是ES6中模板字符的特性。

  styled-components本身是React社區針對JSX產生的一種方案,當然在Vue中通過vue-styledcomponents也能使用該功能,但是使用體驗一般,無論是在模板里還是在JSX中,使用組件都需提前聲明并注入到組件構建參數中,過程十分繁瑣,而且不同于React純JSX的組件渲染語法,Vue中并不能對既有的組件使用styled語法。

  但另一方面,將CSS完全寫在Java中,社區里中也有很多人持反對態度,react-css-modules的作者就專門發文表示反對styled-component這種完全拋棄CSS文件的開發模式。

  總結

  我們在開發之前,面對各種技術方案,一定要選取并組合出最適合自己項目的方案,是選用傳統的CSS預處理器,還是選用PostCSS?是全局手動維護模塊,還是完全交給程序隨機生成類名?都需要結合業務場景、團隊習慣等因素。另一方面,CSS本身并無編程特性,但在其工程化技術的發展中不乏很多優秀的編程思想,無論是自定義DSL還是基于Java,這其中帶給我們思考的正是“編譯思想”。

非常好我支持^.^

(0) 0%

不好我反對

(0) 0%

CSS工程化實踐成果分析下載

相關電子資料下載

      發表評論

      用戶評論
      評價:好評中評差評

      發表評論,獲取積分! 請遵守相關規定!

      ?
      亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
      <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
      <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
      <acronym id="s8ci2"></acronym>
      <acronym id="s8ci2"><center id="s8ci2"></center></acronym>