借助 Webpack 的力量,我們可以在 SPA 大量使用 JS 開發的環境下,一樣使用 JS 的形式來 Import CSS。在 Webpack 的世界,所有 Import 的檔案都稱為 Module,因此我們 Import 的 CSS、LESS 或是 SASS 檔案就概稱為 CSS Module。
我們先拋開 CSS Module 來看看在 React 中使用 CSS 有哪些做法,後面再來選擇 Boilerplate 應該實作何種方法。
直接將 Style 寫成 JS 物件,當作 Component 的 prop 傳遞進去:
class ExampleComponent extends Component { render() { return ( <div style={{ border: '1px solid red', }} > foo bar </div> ); }}
將 CSS 獨立寫在外部檔案,再以 Module 形式載入,此方法必須搭配 Webpack 的設定。
/* styles.css */.redBorder { border: 1px solid red;}
import cx from 'classnames';import styles from './styles.css';
class ExampleComponent extends Component { render() { let { className } = this.props;
return ( <div className={cx(styles.redBorder, className)}> foo bar </div> ); }}
為了避免不同 Component 之間的 className 互相衝突,一般在 Webpack 的設定中會將 中的 class 重新命名,例如加上一段 hash,或是加上 Scope 名稱。所以上例中的 經過 Webpack 的 Loader 轉換後可能會被重新命名為 ,其中 是 Scope, 則是一段 hash。
由於 className 是動態產生的,所以 assign 給 Component 時不能寫死成 ,必須要以變數方式傳遞:。
第三種作法和方法二類似,只是 Webpack 的設定少了一點,使用固定的 className,不做重新命名。
通常這個寫法是用在 Library(例如:react-datesopen_in_new),因為元件的 className 是寫死的,所以我們可以不採用 Library 本身提供的預設樣式自己刻一套,如此才能保留 Library 的彈性。
/* styles.css */.redBorder { border: 1px solid red;}
import cx from 'classnames';import './styles.css';
class ExampleComponent extends Component { render() { return ( <div className={cx('redBorder', className)}> foo bar </div> ); }}
這個方法是最近出現的,筆者也還沒使用過,有興趣的讀者可以看看 styled-componentsopen_in_new 這一套 Library。
我並不擅長前端,所以當初在規劃 Boilerplate 要如何整合 CSS 時並沒有做太多研究,而且開源界的風向也非常亂,前面提及的方法一至方法四都有人使用,當時就隨手挑了方法二 Dynamic ClassName 整合進 Boilerplate 中,而且還搭配了 及 一起使用。
其實越往後寫越發現方法三 Fixed ClassName 才是最佳解,所以在此跟各位讀者抱歉,我們的 Boilerplate 押錯了寶,選到了方法二,日後我應該會找個時間調整成方法三 QQ