css modules和scoped區別

一、css modules是什麼?

A CSS Moduleis a CSS file in which all class names and animation names are scoped locally by default. All URLs ( url(...)) and @importsare in module request format ( ./xxxand ../xxxmeans relative, xxxand xxx/yyymeans in modules folder, i. e. in node_modules).

CSS模塊是一個CSS文件,默認狀況下,全部類名和動畫名都在本地做用域內。全部URL(url(...))@imports均以模塊請求格式表示(./ xxx../ xxx表示相對,xxxxxx / yyy表示模塊文件夾,即在「 node_modules」中)。css

也就是說,css modules是主要爲了解決樣式衝突問題,使得css樣式具備做用域。html

二、vue項目中css modules和scoped區別?

vue項目中有兩種解決css衝突的方案,一種是比較常見的使用scoped。另外一種就是css modules。先對這兩種方案原理作一個簡單介紹,而後比較他們之間的區別:vue

scoped方案

這是在vue項目中很是常見的解決樣式衝突方式,當在style標籤中加上scoped,編譯後會在該vue組件元素上加上hash標識屬性,在vue組件裏的每一個元素都有同一個hash標識屬性。沒法徹底避開css權重和類名重複的問題。
image.pngnode

實例算法

<style scoped> 
.example { 
    color: red; 
} 
</style>  
<template>  
    <div class="example">hi</div>  
</template>

編譯後數組

<style> 
.example[data-v-f3f3eg9] 
{ 
    color: red; 
} 
</style> 
<template> 
    <div class="example" data-v-f3f3eg9>hi</div> 
</template>
css modules方案

產生局部做用域的惟一方法,就是使用一個獨一無二的class的名字,爲全部類名從新生成類名,有效避開了css權重和類名重複的問題,這就是 CSS Modules 的作法。css module直接替換了類名,排除了用戶設置類名影響組件樣式的可能性sass

實例安全

<style module> 
.red { 
    color: red; 
} 
</style>  
<template>  
    // 構建工具會將類名`style.red`編譯成一個哈希字符串,這樣一來,這個類名就變成獨一無二了,只對對應組件有效。
    <p :class="$style.red"> This should be red </p>  
</template>

編譯後app

<style module>
._1yZGjg0pYkMbaHPr4wT6P__1 { 
    color: red; 
} 
</style> 
<template> 
    <p class="_1yZGjg0pYkMbaHPr4wT6P__1"> This should be red </p> 
</template>
兩種方案的區別
  • scoped方案在其餘地方使用相同類名可能仍是會影響組件樣式,若是你子組件的某元素上有一個類已經在這個父組件中定義過了,那麼這個父組件的樣式就會泄露到子組件中。可是css modules方案經過算法計算出惟一類名替換原始類名避免了這種樣式衝突。
//Father.vue
<template>
  <div>
    <son></son>
  </div>
</template>

<script>
import Son from './Son'
export default {
  name: 'Father',
  components: {
    Son
  },
  data () {
    return {}
  }
}
</script>

<style scoped>
.wrapper {
  width: 300px;
  height: 300px;
  line-height: 300px;
  vertical-align: middle;
  background-color: #000;
  color: #fff;
}
</style>
// Son.vue
<template>
  <div class="wrapper">111111</div>
</template>

<script>
export default {
  name: 'Son',
  data () {
    return {}
  }
}
</script>

Father組件的wrapper樣式會滲透到Son組件中並起做用
image.png!工具

  • 還有一些狀況是咱們須要對咱們的子組件的深層結構設置樣式——雖然這種作法並不受推薦且應該避免。爲了簡便起見,咱們假設咱們的父組件如今要對子組件設置樣式,在 scoped 樣式中,這種狀況可使用 >>> 鏈接符(或者 /deep/ )實現。但是別忘記,咱們卻所以失去了組件的封裝效果。這個組件內的全部的被父組件深度選擇器選擇的類的樣式都會被浸染——即使是孫節點。而css modules方案下全部的 CSS 類能夠經過$style對象獲取到,因此咱們能夠經過 props 將這些類傳遞到任何咱們但願的深度中,這樣,在子組件中的任意位置使用這些類就會變得極其容易
// Father.vue
<template>
  <div>
    <son :contentClass="$style.content"></son>
  </div>
</template>

<script>
import Son from './Son'
export default {
  name: 'Father',
  components: {
    Son
  },
  data () {
    return {}
  }
}
</script>

<style lang="scss" module>
.content {
  color: blue;
}
</style>
// Son.vue
<template>
  <div :class="$style.wrapper">
    <span :class="contentClass">111111</span>
  </div>
</template>

<script>
export default {
  name: 'Son',
  props: ['contentClass'],
  data () {
    return {}
  }
}
</script>

<style lang="scss" module>
.wrapper {
  width: 300px;
  height: 300px;
  line-height: 300px;
  vertical-align: middle;
  background-color: #000;
  color: #fff;
}
</style>

效果:

image.png

  • scoped會使標籤選擇器渲染變慢不少倍,而使用class或id則不會。
  • 模塊式 CSS 與 JS 有着很好的互操做性 (interoperability),這一點不僅侷限於 CSS 類。

三、css modules如何使用?

{
    test: /\.(sc|sa|c)ss$/,
    include: [path.join(__dirname, '.././', 'src')],
    // 匹配規則時,只使用第一匹配的數組
    oneOf: [
      // 這裏匹配 `<style module>`
      {
        // 與資源查詢匹配的條件
        resourceQuery: /module/,
        use: [
          // module須要使用vue-style-loader
          'vue-style-loader',
          {
            loader: 'css-loader',
            options: {
              // 開啓 CSS Modules
              modules: true,
              // 自定義生成的類名
              localIdentName: '[name]_[local]_[hash:base64:5]'
            }
          },
          'sass-loader'
        ]
      },
      // 這裏匹配普通的 `<style>` 或 `<style scoped>`
      {
        use: [
          // scoped使用style-loader
          'style-loader',
          'css-loader',
          'sass-loader'
        ]
      }
    ]
}

四、總結

其實兩種方案都很是簡單、易用,在某種程度上解決的是一樣的問題。 那麼你該選擇哪一種呢?

scoped 樣式的使用不須要額外的知識,給人溫馨的感受。它所存在的侷限,也正是它的使用簡單的緣由。它能夠用於支持小型到中型的應用。

在更大的應用或更復雜的場景中,這個時候,對於 CSS 的運用,咱們就會但願它更加顯式,擁有更多的控制權。雖然在模板中大量使用 $style 看起來並不那麼「性感」,但卻更加安全和靈活,爲此咱們只需付出微小的代價。還有一個好處就是咱們能夠用 JS 獲取到咱們定義的一些變量(如色彩值、樣式斷點),這樣咱們就無需手動保持其在多個文件中同步。

參考:
https://juejin.im/post/5b9556...
https://www.jianshu.com/p/255...
http://www.ruanyifeng.com/blo...

相關文章
相關標籤/搜索