首先,咱们来回忆一下「CSS 做用域」这一律念,它的本质是经过让每个选择器成为一个「unique」的存在,这样就天然而然地造成了做用域。javascript
而提到「Vue」中「做用域 CSS」,我想你们应该当即想到以 scoped
的方式造成的带有做用域的 css
。可是,值得一提的是,在「Vue」中还支持了一种「做用域 CSS」,即「CSS Module」。css
说起 「CSS Module」,想必你们会有点陌生,相信有不少同窗在日常开发中都是用 scoped
来实现「Vue」组件中的「做用域CSS」。因此,今天咱们就来详细认知一下这二者。html
「scoped 做用域」是「Vue」经过「postcss」来实现对每个在 scoped
标签中定义的选择器的特殊做用域标识,例如:vue
<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>
标识后展现在页面上的:java
<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
。git
而且,在咱们日常开发中,很常见的场景就是咱们在使用一些已有的组件或第三方组件时,咱们须要对原有组件的样式进行一些微小的改动。那么,这个时候就须要使用穿透来实现样式的改动,例如:github
<style> div >>> .out-box { background-color: #aaf; } </style>
这里须要注意的是 >>> 只是一种穿透方式,并非全部场景下都是能够用 >>> 实现。例如,「iView」须要使用 /deep/ 的方式,「ElementUI」须要使用 ::v-deep 的方式。
相比较「scoped 做用域」,「CSS Modeul 做用域」它所具有的能力更强,因此内容也相对较多。app
「CSS Module」指的是能够将一个定义好的「CSS」文件以变量的形式导入,而后经过使用这个变量对「HTML」中的元素进行样式的修饰,例如:post
a.cssspa
.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」应该绰绰有余。
写做不易,若是你以为有收获的话,能够帅气三连击!!!