sass、less 经过 @import
,部分解决的 css 模块化的问题。css
因为 css 是全局的,在被引入的文件和当前文件出现重名的状况下,前者样式就会被后者覆盖。
在引入一些公用组件,或者多人协做开发同一页面的时候,就须要考虑样式会不会被覆盖,这很麻烦。html
// file A .name { color: red } // file B @import "A.scss"; .name { color: green }
css 全局样式的特色,致使 css 难以维护,因此须要一种 css “局部”样式的解决方案。
也就是完全的 css 模块化,@import
进来的 css 模块,须要隐藏本身的内部做用域。react
经过在每一个 class 名后带一个独一无二 hash 值,这样就不有存在全局命名冲突的问题了。这样就至关于伪造了“局部”样式。webpack
// 原始样式 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-loader
组件,自带了 CSS Modules,经过简单的配置便可使用。git
{ test: /\.css$/, loader: "css?modules&localIdentName=[name]__[local]--[hash:base64:5]" }
命名规范是从 BEM 扩展而来。github
Block: 对应模块名 [name]
web
Element: 对应节点名 [local]
sass
Modifier: 对应节点状态 [hash:base64:5]
app
使用 __ 和 -- 是为了区块内单词的分割节点区分开来。
最终 class 名为 styles__title--3zyde
。less
在实际生产中,结合 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
的库,来减小代码的书写,感兴趣的同窗能够研究下。
参考资料:
《深刻React技术栈》
css-modules
CSS Modules 用法教程