react
中的樣式問題,一瞬間腦殼沒反應上來好像還回答錯了,有點尷尬水一篇文章記錄一下。react
父子組件demo
中,實際效果與書寫的樣式不太同樣。直接上代碼描述問題:javascript
Parent.js
import React from 'react';
import Child from './Child'
import './Parent.less'
function Parent() {
return (
<div className="parent"> <Child/> <div className='component'>parent</div> </div>
);
}
export default Parent;
複製代碼
Parent.less
.parent{
background-color: blue;
.component{
color: white;
}
}
複製代碼
import React from 'react';
import './Child.less'
function Child() {
return (
<div className="child"> <div className='component'>Child</div> </div>
);
}
export default Child
複製代碼
Child.less
.child{
background-color: red;
.component{
color: black;
}
}
複製代碼
大概看一下代碼,是有一個Parent
的父組件,藍底白字。還有一個Child
的子組件,紅底黑字。 那麼實際渲染出的樣式是什麼樣子的呢。以下圖: css
實際看到的效果確實藍底白字與紅底白字,爲何與寫的代碼有出入呢。html
打開調試工具,看到子組件被渲染成一個<div class="component">Child</div>
可是樣式卻被父組件的樣式給覆蓋變成了白色,java
緣由:這是由於在w3c 規範中,CSS 始終是「全局的」。在傳統的 web 開發中,最爲頭痛的莫過於處理 CSS 問題。由於全局性,明明定義了樣式,但就是不生效,緣由多是被其餘樣式定義所強制覆蓋。react
.parent .component
和.child .component
是父級覆蓋子級?這就要涉及到瀏覽器渲染原理與css的瀏覽器解析原則則了webpack
CSSOM(CSS Object Model)
。DOM
和CSSOM
合併爲渲染樹(rendering tree)
將會被建立,表明一系列將被渲染的對象。佈局layout
。瀏覽器使用一種流式處理的方法,只須要一次繪製操做就能夠佈局全部的元素。painting
。須要注意的是,以上五個步驟並不必定一次性順序完成,好比DOM或CSSOM被修改時,亦或是哪一個過程會重複執行,這樣才能計算出哪些像素須要在屏幕上進行從新渲染。而在實際狀況中,JavaScript和CSS的某些操做每每會屢次修改DOM或者CSSOM。git
看一個例子:github
.nav h3 span {font-size: 16px;}
複製代碼
在咱們不知道規則的狀況下,咱們是這樣猜想的,按照常人的思惟從左到右。先是找到.nav
,而後向下匹配全部的h3
和span
標籤。若是在向下匹配的過程當中,沒有匹配上的則回溯到上一級繼續匹配其餘子葉結點。web
但實際上,CSS選擇器讀取順序是從右到左瀏覽器
若是是這樣的規定的話,仍是上面的例子就變成了,先找到全部的span
標籤,而後找span
標籤是h3
的,而後再延着h3
往上尋找,這時候發現一個選擇器的類名爲.nav
就把這個節點加入結果集;若是一直往上找直到html
標籤都沒找到的話,就放棄這條線,換到另外一個span
進行尋找。
那麼來看咱們的這個Demo
中的結構
<div class="parent">
<div class="child">
<div class="component">Child</div>
</div>
<div class="component">parent</div>
</div>
複製代碼
瀏覽器先找到.component
往上尋找,發現了.child .component
這時候渲染出樣式爲黑色,而後接着向上尋找發現了.parent .component
發現存在這個CSS規則,因此這時候顏色變成了白色
問題找到了,是由於樣式覆蓋了,那麼如何解決這個問題了。這裏咱們採用了CSS Modules
方案。
什麼是CSS Modules
? 把CSS
劃分模塊,自動爲類名後面生成一個hash值保證類名全局惟一。
CSS Modules
的使用
create-react-app
建立項目,修改webpack.config.js
// parent.js
import styles from './Parent.less'
<div className={styles.parent}>
<Child/>
<div className={styles.component}>
css modules parent
</div>
</div>
//child.js
import styles from './Child.less'
<div className={styles.child}>
<div className={styles.component}>
css modules child
</div>
</div>
複製代碼
配置完成以後發現樣式類名變成了hash值,這樣即保證了類名的惟一不會存在覆蓋的問題