首頁  >  文章  >  web前端  >  聊聊css為什麼需要模組化?怎麼進行模組化?

聊聊css為什麼需要模組化?怎麼進行模組化?

藏色散人
藏色散人轉載
2021-10-25 16:37:581866瀏覽

css 「局部」樣式

sass、less 透過@import ,部分解決的css 模組化的問題。

由於 css 是全域的,在被引入的檔案和目前檔案出現重名的情況下,前者樣式就會被後者覆寫。
在引進一些公用元件,或是多人合作開發同一頁的時候,就需要考慮樣式會不會被覆蓋,這很麻煩。

// file A
.name {
    color: red
}

// file B
@import "A.scss";
.name {
    color: green
}

css 全域樣式的特點,導致 css 難以維護,所以需要 css “局部”樣式的解。
也就是徹底的 css 模組化,@import 進來的 css 模組,需要隱藏自己的內部作用域。

CSS Modules 原理

透過在每個 class 名後帶一個獨一無二 hash 值,這樣就不有存在全域命名衝突的問題了。這樣就相當於偽造了「局部」樣式。

// 原始样式 styles.css
.title {
  color: red;
}

// 原始模板 demo.html
import styles from 'styles.css';

<h1 class={styles.title}>
  Hello World
</h1>


// 编译后的 styles.css
.title_3zyde {
  color: red;
}

// 编译后的 demo.html
<h1 class="title_3zyde">
  Hello World
</h1>

webpack 與 CSS Modules

webpack 自帶的 css-loader 元件,自帶了 CSS Modules,透過簡單的設定即可使用。

{
    test: /\.css$/,
    loader: "css?modules&localIdentName=[name]__[local]--[hash:base64:5]"
}

命名規格是從 BEM 擴展而來。

  • Block: 對應模組名稱[name]

  • #Element: 對應節點名稱[local]

  • Modifier: 對應節點狀態[hash:base64:5]

使用__ 和--是為了區塊內單字的分割節點區分開來。
最終 class 名稱為 styles__title--3zyde

在生產環境中使用

在實際生產中,結合 sass 使用會更加便利。以下是結合 sass 使用的 webpack 的設定檔。

{
    test: /\.scss$/,
    loader: "style!css?modules&importLoaders=1&localIdentName=[name]__[local]--[hash:base64:5]!sass?sourceMap=true&sourceMapContents=true"
}

通常除了局部樣式,還需要全域樣式,例如 base.css 等基礎檔。
將公用樣式檔案和元件樣式檔分別放入到兩個不同的目標下。如下。

.
├── app                      
│   ├── styles               # 公用样式
│   │     ├── app.scss       
│   │     └── base.scss      
│   │
│   └── components           # 组件
          ├── Component.jsx  # 组件模板
          └── Component.scss # 组件样式

然後透過 webpack 配置,將在 app/styles 資料夾的外的(exclude) scss 檔案"局部"化。

{
    test: /\.scss$/,
    exclude: path.resolve(__dirname, 'app/styles'),
    loader: "style!css?modules&importLoaders=1&localIdentName=[name]__[local]--[hash:base64:5]!sass?sourceMap=true&sourceMapContents=true"
},
{
    test: /\.scss$/,
    include: path.resolve(__dirname, 'app/styles'),
    loader: "style!css?sass?sourceMap=true&sourceMapContents=true"
}

有時候,一個元素有多個 class 名,可以透過  join(" ")  或字串模版的方式來為元素增加多個 class 名。

// join-react.jsx
<h1 className={[styles.title,styles.bold].join(" ")}>
  Hello World
</h1>

// stringTemp-react.jsx
<h1 className={`${styles.title} ${styles.bold}`}>
  Hello World
</h1>

如果只寫一個 class 就能把樣式定義好,那麼最好把所有樣式寫在一個 class 中。
所以,如果我們使用了多個 class 定義樣式,通常會帶一些邏輯判斷。這時候寫起來就會麻煩不少。

引入 classnames ,也就是可以解決給元素寫多個 class 名的問題,也可以解決寫邏輯判斷的麻煩問題。

classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'

// lots of arguments of various types
classNames('foo', { bar: true, duck: false }, 'baz', { quux: true }); // => 'foo bar baz quux'

// other falsy values are just ignored
classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1'

引入CSS Modules 的樣式模組,每個class 每次都要寫styles.xxx 也是很麻煩,在《深入React技術棧》提到了react-css -modules 的函式庫,來減少程式碼的書寫,有興趣的同學可以研究下。

推薦學習:《css影片教學

以上是聊聊css為什麼需要模組化?怎麼進行模組化?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除