爲何個人樣式不起做用?

關於

  • 今天被人問了一個關於react中的樣式問題,一瞬間腦殼沒反應上來好像還回答錯了,有點尷尬水一篇文章記錄一下。
  • 問題描述:在一個react父子組件demo中,實際效果與書寫的樣式不太同樣。

問題復現

直接上代碼描述問題:javascript

  1. 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;
複製代碼
  1. Parent.less
.parent{
  background-color: blue;
  .component{
    color: white;
  }
}
複製代碼
  1. Child.js
import React from 'react';
import './Child.less'

function Child() {
    return (
        <div className="child"> <div className='component'>Child</div> </div>
    );
}

export default Child
複製代碼
  1. 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

瀏覽器渲染

  1. 瀏覽器將獲取的HTML文檔解析成DOM樹。
  2. 處理CSS標記,構成層疊樣式表模型CSSOM(CSS Object Model)
  3. DOMCSSOM合併爲渲染樹(rendering tree)將會被建立,表明一系列將被渲染的對象。
  4. 渲染樹的每一個元素包含的內容都是計算過的,它被稱之爲佈局layout。瀏覽器使用一種流式處理的方法,只須要一次繪製操做就能夠佈局全部的元素。
  5. 將渲染樹的各個節點繪製到屏幕上,這一步被稱爲繪製painting

須要注意的是,以上五個步驟並不必定一次性順序完成,好比DOM或CSSOM被修改時,亦或是哪一個過程會重複執行,這樣才能計算出哪些像素須要在屏幕上進行從新渲染。而在實際狀況中,JavaScript和CSS的某些操做每每會屢次修改DOM或者CSSOM。git

css的瀏覽器解析原則

看一個例子:github

.nav h3 span {font-size: 16px;}
複製代碼

在咱們不知道規則的狀況下,咱們是這樣猜想的,按照常人的思惟從左到右。先是找到.nav,而後向下匹配全部的h3span標籤。若是在向下匹配的過程當中,沒有匹配上的則回溯到上一級繼續匹配其餘子葉結點。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的使用

  1. 使用create-react-app建立項目,修改webpack.config.js

  1. 在組件中使用
// 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值,這樣即保證了類名的惟一不會存在覆蓋的問題

最後

相關文章
相關標籤/搜索