你須要知道的 Vue.js 中做用域 CSS 的那點事

前言

首先,咱們來回憶一下「CSS 做用域」這一律念,它的本質是經過讓每個選擇器成爲一個「unique」的存在,這樣就天然而然地造成了做用域。javascript

而提到「Vue」中「做用域 CSS」,我想你們應該當即想到以 scoped 的方式造成的帶有做用域的 css。可是,值得一提的是,在「Vue」中還支持了一種「做用域 CSS」,即「CSS Module」。css

說起 「CSS Module」,想必你們會有點陌生,相信有不少同窗在日常開發中都是用 scoped 來實現「Vue」組件中的「做用域CSS」。因此,今天咱們就來詳細認知一下這二者。vue

1、scoped 做用域

「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」加上了一串 attrgithub

而且,在咱們日常開發中,很常見的場景就是咱們在使用一些已有的組件或第三方組件時,咱們須要對原有組件的樣式進行一些微小的改動。那麼,這個時候就須要使用穿透來實現樣式的改動,例如:web

<style> div >>> .out-box {  background-color: #aaf; } </style> 複製代碼

這裏須要注意的是 >>> 只是一種穿透方式,並非全部場景下都是能夠用 >>> 實現。例如,「iView」須要使用 /deep/ 的方式,「ElementUI」須要使用 ::v-deep 的方式。app

2、CSS Module 做用域

相比較「scoped 做用域」,「CSS Modeul 做用域」它所具有的能力更強,因此內容也相對較多。編輯器

什麼是 CSS Module

「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 上自行閱讀

CSS Module 在 Vue 中的應用

回到本文所說的,在「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,從而實現切換組件不一樣的背景色。

3、兩種方式的優劣勢

「scoped 做用域」:

  • 對組件沒有硬性要求
  • 不易於管理組件樣式,須要藉助第三方變量定義支持
  • 易於覆蓋組件樣式,即經過穿透來實現對樣式的覆蓋

「CSS Module 做用域」:

  • 適合於高度沉澱下的組件使用
  • 易於管理組件樣式,便可以經過 style 管理組件中的選擇器
  • 組件樣式沒法經過外部直接覆蓋

這裏所說的管理,是指經過JavaScript便捷地控制組件樣式。

寫在最後

其實,對比「scoped」和「CSS Module」二者,各有千秋。至於,要用哪一着得看具體需求,建議大項目中可使用「CSS Module」,小項目的話用用「scoped」應該綽綽有餘。

寫做不易,若是你以爲有收穫的話,能夠帥氣三連擊!!!

相關文章
相關標籤/搜索