Scoped CSS

Scoped CSS

在Vue中,我们可以通过在<style>标签上面添加scoped来使得下面的CSS只作用于当前的组件,这相当于就是Vue-loader在解析vue文件的时候,帮我们做了 CSS的模块化。
其实在vue-loader也是通过PostCSS来帮我们实现的,它的实现原理也是很简单的,就是给每个CSS样式(我们一般是是通过类选择器写样式,所以下面就以类来说明)作用的DOM元素添加一个唯一的属性值。然后我们在使用选择器获取这个样式的时候同时也使用属性选择器获取这个唯一的属性。这样就实现了每个组件下面的样式都不会和其他的组件下面的样式冲突了。反应到实际,就是如下样子。
下面是我们写的:

  1. <style scoped>
  2. .example {
  3. color: red;
  4. }
  5. </style>
  6. <template>
  7. <div class="example">hi</div>
  8. </template>

实际PostCSS转换后,在页面中的结果

  1. <style>
  2. /* 这里相当于同时类选择器+属性选择器作用
  3. data-v- 是vue设置的格式,
  4. 而后面的是生成的hash值
  5. */
  6. .example[data-v-f3f3eg9] {
  7. color: red;
  8. }
  9. </style>
  10. <template>
  11. <div class="example" data-v-f3f3eg9=''>hi</div>
  12. </template>

使用 scoped 后,父组件的样式将不会渗透到子组件中。不过一个子组件的根节点会同时受其父组件的 scoped CSS 和子组件的 Scoped CSS 的影响。这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。

深度作用选择器

如果我们希望 Scoped 样式中的一个选择器能够作用得“更深”,例如影响子组件,你可以使用 >>> 操作符:

  1. <style scoped>
  2. .a >>> .b {
  3. /* ... */
  4. }
  5. </style>

上述代码将会编译成:

  1. .a[data-v-f3f3eg9] .b {
  2. /* ... */
  3. }

有些像 Sass / Scss 之类的预处理器无法正确解析 >>>。
这种情况下你可以使用/deep/::v-deep(常用) 操作符取而代之——两者都是 >>> 的别名,同样可以正常工作。

注意点: 我们在scoped中好像要尽量的避免使用标签选择器,来获取元素,在vue-loader中有这么一句话。 考虑到浏览器渲染各种 CSS 选择器的方式,当 p { color: red } 是 scoped 时 (与属性选择器组合使用时) 会慢很多倍。 意思是:标签选择器+属性选择器会慢很多倍吗?所以推荐我们说过类选择器和id选择器。

CSS Module

CSS Module也是一种解决CSS 模块化的方式(不和Scoped一样只在vue中),CSS Module是更加通用的在普通的CSS文件中 ,React中,都可以使用的。CSS Modules 是一个流行的,用于模块化和组合 CSS 的系统。vue-loader 提供了与 CSS Modules 的一流集成,可以作为模拟 scoped CSS 的替代方案