react中css作用域問題探究
場景1
新建元件Page1與Page2,兩個元件的根節點className設定為一樣
目錄結構如下:
src/pages/page1/index.js
import React from 'react'
import './index.css'
function Page1() {
return (
<div className='title'>page1</div>
)
}
export default Page1
src/pages/page1/index.css
.title {
background-color: #ccc;
}
src/pages/page2/index.js
import React from 'react'
import './index.css'
function Page2() {
return (
<div className='title'>page2</div>
)
}
export default Page2
src/pages/page2/index.css
.title {
background-color: red;
}
src/app.js
import Page1 from './pages/page1'; import Page2 from './pages/page2'; function App() { return ( <div className="App"> <header className="App-header"> <Page1 /> <Page2 /> </header> </div> ); } export default App;
效果圖如下:
會發現兩個元件之間樣式會相互影響?是因為最終打包出來的樣式渲染到節點上是這樣的:
結論:CSS檔案分離 !== CSS作用域隔離
CSS的一些常見問題
- 全域性汙染
- 命名混亂
- 程式碼關係複雜
- 無法共享變數
- 複用性差,難維護
實現CSS樣式隔離的幾種方式
- 行內樣式,直接在js中編寫css
- namespaces
- CSS-in-JS,常見的解決方案有styled-components、styled-jsx、react-style
- CSS Modules
行內樣式
優點:
- 寫法簡單
- 優先順序高,有類似獨立作用域
缺點:
- 無法複用
- 內容與樣式沒分離,難維護
src/pages/page5/index.js
import React from 'react'
function Page5() {
return (
<div style={{ background: 'red' }}>page5</div>
)
}
export default Page5
src/pages/page6/index.js
import React from 'react'
function Page6() {
return (
<div style={{background: 'green'}}>page6</div>
)
}
export default Page6
效果圖:
namespaces
通過css樣式變數的命令來做到作用域隔離
優點:
- 寫法簡單,沒什麼需要特別注意的
缺點:
- 團隊協作是還是容易出現命名重複的情況出現
src/pages/page7/index.js
import React from 'react'
import styles from './index.less'
function Page7() {
return (
<div className={styles.page7}>
page7
<p>哈哈哈,我是通過namespaces方案區分的</p>
</div>
)
}
export default Page7
src/pages/page7/index.less
.page7 {
background-color: red;
p {
font-size: 15px;
color: #fff;
}
}
src/pages/page8/index.js
import React from 'react'
import styles from './index.less'
function Page8() {
return (
<div className={styles.page8}>
page8
<p>哈哈哈,我是通過namespaces方案區分的</p>
</div>
)
}
export default Page8
src/pages/page8/index.less
.page8 {
background-color: #398def;
p {
font-size: 30px;
}
}
效果圖:
CSS-in-JS
通過寫js的方式來寫css,react官方也是推薦這樣來寫。官方文件
CSS-in-JS地址,可以看到常見的基於CSS-in-JS的解決方案
優點:
- 解決了css作用域的問題
- 複用性
缺點:
- 一定的學習成本
- 與常見的寫法不同
CSS Module
CSS Module本質是通過三方工具如webpack等,把css的變數唯一化
效果圖:
從上面可以看出,我設定的類名為styles.header,但是在經過編譯後為index__header__2zovj,其實配置一下css-loader開啟css modules即可
配置方式:
{
test: /\.css$/,
loader: "style-loader!css-loader?modules"
}
大功告成!!!
總結
其實css作用域的本質,就是頁面中的類名都是唯一的。現在通過編譯工具,可以把頁面中類名編譯為一個唯一的類名,這樣就不會出現類名相同的情況下相互影響。
綜合下來,CSS Module會比CSS-in-JS使用起來更方便,對程式碼的入侵更小,寫法也更符合常見的形式,結合三方工具配置起來也挺方便的。