由于原生CSS的規(guī)則都是全局的,任何一個(gè)組件內(nèi)的樣式規(guī)則,都會(huì)對(duì)全部組件生效,導(dǎo)致全局樣式污染;
為了解決這個(gè)問題,我們可以給不同的頁面寫不同的類名,但是這樣特別的繁瑣,而且多人協(xié)同開發(fā)難免會(huì)出現(xiàn)類名重復(fù);
css-module 解決了這個(gè)問題,通過自動(dòng)附上獨(dú)一無二的哈希字符串(需配置),避免選擇器重名;
在使用css-module 時(shí)會(huì)發(fā)現(xiàn)當(dāng)前組件樣式表的類樣式對(duì)嵌套組件內(nèi)的類不生效的情況,以下是嵌套自定義組件和antd組件的例子
注:以下樣式因項(xiàng)目設(shè)置可能與原本的antd組件風(fēng)格有些不同,但不影響原理理解
- 示例
// DemoPage 組件
import { List } from 'antd';
const { Item } = List;
import styles from './DemoPage.less';
import MyComponent from './MyComponent'
render() {
const demoList = [
{
id: 1,
text: '這里是antd的 list 組件內(nèi)部1111'
},
{
id: 2,
text: '這里是antd的 list 組件內(nèi)部2222'
},
]
return (
<div className={styles.root}>
<div>no class (這里是原生元素div)</div>
<div className='ant-list-item'>no style (這里是原生元素div)</div>
<div className={styles['ant-list-item']}>has styles (這里是原生元素div)</div>
<List bordered style={{marginTop: '30px', border: '1px solid rgb(34, 177, 76)'}}>
{demoList.map(item => (
<Item key={item.id}>
{item.text}
</Item>
))}
</List>
<MyComponent></MyComponent>
</div>
);
}
// MyComponent 組件
import React from "react";
import styles from "./MyComponent.less";
const MyComponent = function MyComponent(props) {
return (
<div style={{marginTop: '30px', border: '1px solid rgb(255, 128, 64)'}}>
這里是自定義組件
<div>no class (這里是原生元素div)</div>
<div className='ant-list-item'>no style (這里是原生元素div)</div>
<div className={styles['ant-list-item']}>has styles (這里是原生元素div)</div>
</div>
);
}
export default MyComponent;
- 初始樣式效果(以下皆指DemoPage組件的樣式表)
.root {
background-color: #fff;
padding: 24px 32px;
border-radius: 4px;
}

初始樣式效果.png
- 問題:樣式表里寫的類名無法對(duì)內(nèi)部嵌套組件的同類名元素生效,因?yàn)橥ㄟ^編譯后的樣式表都會(huì)帶上唯一的哈希后綴,而自定義組件和antd等外部引入的組件類名沒有該后綴,所以無法匹配
// 編譯后類名類似 root___xxxx
// xxxx指生成的哈希字符串
.root {
background-color: #fff;
padding: 24px 32px;
border-radius: 4px;
// 編譯后類名類似 ant-list-item___oooo
// oooo指生成的哈希字符串,不同類名生成的哈希字符串不同
.ant-list-item {
background-color: red;
}
}

只對(duì)引入該樣式表的當(dāng)前組件生效.png

不同的哈希字符串導(dǎo)致了嵌套組件的樣式不生效.png
- 解決嵌套組件樣式不生效問題:在類名外嵌套
:global,凡是這樣聲明的class,在樣式表被編譯時(shí)都不會(huì)被編譯成哈希字符串,即類名會(huì)保持原樣,即可作用于引用的antd組件或未使用樣式表的自定義組件類名
// 編譯后 root___xxxx
.root {
background-color: #fff;
padding: 24px 32px;
border-radius: 4px;
// 編譯后 ant-list-item; global下的(包括嵌套)類名都不會(huì)帶上哈希字符串
// 相當(dāng)于
// .root___xxxx .ant-list-item {
// background-color: red;
// }
:global {
.ant-list-item {
background-color: red;
}
}
}

添加 :global 后.png
- 樣式表里用 元素選擇器,會(huì)對(duì)該樣式表下的所有(包括組件內(nèi))的元素生效
// 編譯后 root___xxxx
.root {
background-color: #fff;
padding: 24px 32px;
border-radius: 4px;
// 元素選擇器編譯后還是元素,不帶哈希值所以還是能影響組件內(nèi)部組件的樣式
div {
background-color: red;
}
}

css-module中的元素選擇器會(huì)照常生效.png