首先,咱們來回憶一下「CSS 做用域」這一律念,它的本質是經過讓每個選擇器成爲一個「unique」的存在,這樣就天然而然地造成了做用域。javascript
而提到「Vue」中「做用域 CSS」,我想你們應該當即想到以 scoped
的方式造成的帶有做用域的 css
。可是,值得一提的是,在「Vue」中還支持了一種「做用域 CSS」,即「CSS Module」。css
說起 「CSS Module」,想必你們會有點陌生,相信有不少同窗在日常開發中都是用 scoped
來實現「Vue」組件中的「做用域CSS」。因此,今天咱們就來詳細認知一下這二者。vue
「scoped 做用域」是「Vue」經過「postcss」來實現對每個在 scoped
標籤中定義的選擇器的特殊做用域標識,例如:java
<template>
<div id="app"> <div class="out-box"> </div> </div> </template> <style lang="scss" scoped> #app { .out-box { width: 200px; height: 200px; background-color: #faa; } } </style> 複製代碼
標識後展現在頁面上的:git
<div data-v-7ba5bd90 id="app">
<div data-v-7ba5bd90 class="out-box"> </div> </div> <style> #app .out-box[data-v-7ba5bd90] { width: 200px; height: 200px; background-color: #faa; } </style> 複製代碼
能夠看到,本質上是在原有的「選擇器」的基礎上經過「postcss」加上了一串 attr
。github
而且,在咱們日常開發中,很常見的場景就是咱們在使用一些已有的組件或第三方組件時,咱們須要對原有組件的樣式進行一些微小的改動。那麼,這個時候就須要使用穿透來實現樣式的改動,例如:web
<style> div >>> .out-box { background-color: #aaf; } </style> 複製代碼
這裏須要注意的是 >>> 只是一種穿透方式,並非全部場景下都是能夠用 >>> 實現。例如,「iView」須要使用 /deep/ 的方式,「ElementUI」須要使用 ::v-deep 的方式。app
相比較「scoped 做用域」,「CSS Modeul 做用域」它所具有的能力更強,因此內容也相對較多。編輯器
「CSS Module」指的是能夠將一個定義好的「CSS」文件以變量的形式導入,而後經過使用這個變量對「HTML」中的元素進行樣式的修飾,例如:post
a.css
.box {
width: 100%; height: 100%; background-color: #afa; } 複製代碼
b.js
import style from './a.css'
const boxElem = document.createElement('div'); boxElem.className = style.box 複製代碼
而後,渲染到頁面的時候,它對應的 HTML 看起來會是這樣:
<div class="a-box_jlpNx"></div>
複製代碼
能夠看出,此時的「類選擇器」一樣是隨機生成的,這也是「CSS Module」造成做用域的所在。
值得一提的是,「CSS Module」還具有其餘的能力,例如能夠定義全局的「選擇器」,寫起來會是這樣:
:global(.title) {
color: green; } 複製代碼
接下來的使用和局部的同樣。至於,其餘用法,有興趣的同窗能夠去 GitHub 上自行閱讀
回到本文所說的,在「Vue」中也對「CSS Module」作了相應的支持,當咱們在 style 標籤上添加 module 屬性時,「Vue」 會在當前「組件實例」上注入一個計算屬性 $style
,而後咱們能夠經過 $style
來使用咱們定義好的「選擇器」,例如:
HelloWorld.vue
<template>
<div> <div :class="$style['inner-box']"></div> </div> </template> <style lang="scss" module> .inner-box { width: 100px; height: 100px; background-color: #aaf; } </style> 複製代碼
而後,它渲染到頁面時,對於的 HTML 會是這樣:
<div class="HelloWorld_inner-box_jlpNx"></div>
複製代碼
那麼,這個時候,又回到和「scoped 做用域」同樣的問題,使用了「CSS Module」來定義組件的樣式,那麼我在使用它的時候,如何進行覆蓋?
標準的答案,對於「CSS Module」並無覆蓋的說法,有的只是爲一個組件設置不一樣的主題。
可是,若是真的須要弄,那隻能經過對該模塊對應的
style
標籤中定義你須要的樣式,而後根據傳入組件的props
來動態綁定class
那麼,爲組件設置主題,咱們須要在設計組件的時候,對這個組件預留 props
,並將該 props
添加到 $style
中,而後在這個組件中的相應元素中使用,例如:
Box.vue 組件
<template>
<div> <div :class="$style[themeColor]"></div> </div> </template> <script> export default { props: { themeColor: { type: String, default: 'line' } } }; </script> <style lang="scss" module> .line { width: 100px; height: 100px; background-color: #aaf; } .card { background-color: #aaf; } </style> 複製代碼
而後,咱們在使用該組件的時候經過 props
傳入 line
或者 card
,從而實現切換組件不一樣的背景色。
「scoped 做用域」:
「CSS Module 做用域」:
style
管理組件中的選擇器
這裏所說的管理,是指經過
JavaScript
便捷地控制組件樣式。
其實,對比「scoped」和「CSS Module」二者,各有千秋。至於,要用哪一着得看具體需求,建議大項目中可使用「CSS Module」,小項目的話用用「scoped」應該綽綽有餘。
寫做不易,若是你以爲有收穫的話,能夠帥氣三連擊!!!