有趣的 React 系列 – CSS module (樣式到底聽誰的?)

舉個例子

假設現在我們有四個檔案,App.js、App.css、Child.js、Child.css

App.js 包含:

import "./App.css";
import Child from "./Child";

function App() {
  return (
    <div>
      <h2>App</h2>
      <ul>
        <li>11111</li>
        <li>22222</li>
        <li>33333</li>
      </ul>
      <Child />
    </div>
  );
}

export default App;

App.css 包含:

li {
  width: 150px;
  background-color: burlywood;
}

Child.js 包含:

import "./Child.css";

function Child() {
  return (
    <div>
      <h2>Child</h2>
      <ul>
        <li>11111</li>
        <li>22222</li>
        <li>33333</li>
      </ul>
    </div>
  );
}

export default Child;

Child.css 包含:

li {
    width: 200px;
    background-color: seagreen;
  }

現在我們 App 組件中的清單和 Child 組件 中的清單底色分別會是什麼呢?

image 5 有趣的 React 系列 - CSS module (樣式到底聽誰的?)

答案是,同為綠色,你猜到了嗎?

image 6 有趣的 React 系列 - CSS module (樣式到底聽誰的?)

打開控制台,我們可以發現其實兩個組件的CSS都有在裡面,只不過 App 的樣式被 Child 的覆蓋掉了,因此兩個清單都會套用到 Child.css 中的 li 樣式:

image 7 有趣的 React 系列 - CSS module (樣式到底聽誰的?)

解決辦法

那這樣的話,我應該如何讓兩個組件之間的樣式互不衝突呢?

這時候我們可以用到 module

將 Child.css 改名為 Child.module.css 並且修改 Child.js 中引入的 css 路徑:

image 8 有趣的 React 系列 - CSS module (樣式到底聽誰的?)
import "./Child.module.css"; // 修改為 Child.module.css

function Child() {
  return (
    <div>
      <h2>Child</h2>
      <ul>
        <li>11111</li>
        <li>22222</li>
        <li>33333</li>
      </ul>
    </div>
  );
}

export default Child;

此時你會發現沒有任何的變化,這是為什麼呢?

image 9 有趣的 React 系列 - CSS module (樣式到底聽誰的?)

那是因為使用 css module 要透過 className 的方式來定義樣式,因此我們需要將 Child.module.css 中的 li 改為 .item

.item {
  width: 200px;
  background-color: seagreen;
}

並且將 Child.js 中的 li 加上 className="item"

import "./Child.module.css";

function Child() {
  return (
    <div>
      <h2>Child</h2>
      <ul>
        <li className="item">11111</li>
        <li className="item">22222</li>
        <li className="item">33333</li>
      </ul>
    </div>
  );
}

export default Child;

然後你會驚奇的發現還是沒有任何的變化,並且 Child 的 classname 變成了很奇怪的東西 .Child_item__3v6sL,構成為:組件名稱_classname__一串隨機產生的字串,我們總不可能直接複製它作為 ClassName 吧?

image 10 有趣的 React 系列 - CSS module (樣式到底聽誰的?)

所以我們應該修改引入 CSS 檔的方式為 import style from "./Child.module.css";,並且將 className 改為 className={style.item}

import style from "./Child.module.css";

function Child() {
  return (
    <div>
      <h2>Child</h2>
      <ul>
        <li className={style.item}>11111</li>
        <li className={style.item}>22222</li>
        <li className={style.item}>33333</li>
      </ul>
    </div>
  );
}

export default Child;

如此一來便能達到我們所希望的效果了。

image 11 有趣的 React 系列 - CSS module (樣式到底聽誰的?)
image 12 有趣的 React 系列 - CSS module (樣式到底聽誰的?)

總結

總結一下 CSS module:

  1. CSS 檔名以 xxx.module.css 命名, 如果是 SCSS 就是 xxx.module.scss
  2. 在 import 時給予變數名稱 (ex: import style from "./child.module.css";)
  3. className 傳入變數底下定義的 class

第三點特別解釋一下,你可以嘗試輸出 style 看會得到什麼內容:

import style from "./Child.module.css";
console.log(style);
image 13 有趣的 React 系列 - CSS module (樣式到底聽誰的?)

你會發現它會輸出一個 object 裡面包含 Child.module.css 中定義的 class。

假設我的 Child.module.css 中定義三個 class:

.item {
  width: 200px;
  background-color: seagreen;
}

.book {
  background-color: aqua;
  font-size: 18px;
}

.header {
  font-size: 24px;
  width: 300px;
}

那麼它就會輸出這些 class 名稱,因此我們只需要透過 style.className 即可獲取自動產生的 class 名稱:

image 14 有趣的 React 系列 - CSS module (樣式到底聽誰的?)
4e52d54f6bc42abb41d26eb5b0df6517?s=250&d=wavatar&r=g 有趣的 React 系列 - CSS module (樣式到底聽誰的?)
0 0 評分數
Article Rating
訂閱
通知
guest
0 Comments
在線反饋
查看所有評論