FrankKai.github.io icon indicating copy to clipboard operation
FrankKai.github.io copied to clipboard

Scoped CSS是什么?

Open FrankKai opened this issue 5 years ago • 0 comments

  • 混入本地和全局的样式(Mixing Local and Global Styles)
  • 子组件根元素
  • 深度选择器
  • 动态生成内容
  • 时刻提醒自己

当一个<style>标签有scoped属性时,它的CSS只作用于当前组件的元素。这和Shadow DOM的样式封装是一样的。它有一些警告(caveats),但是不需要任何填充(polyfill)。是通过PostCSS实现转换的:

<style scoped>
.example {
    color: red;
}
</style>

<template>
    <div class="example">hi</div>
</template>

转化成下面的:

<style>
// 选择有data-v-f3f3eg9属性,并且class名为example的元素
.example[data-v-f3f3eg9] {
    color: red;
}
</style>

<template>
    <div class="example" data-v-f3f3eg9>hi</div>
</template>

混入本地和全局的样式(Mixing Local and Global Styles)

同一个组件里,可以同时包含本地样式和全局样式。

<style>
/* global styles */
</style>

<style scoped>
/* local styles */
</style>

子组件根元素

  • 有了scoped属性后,父组件的样式不会漏进(leak into)子组件。
  • 然而,一个子组件的根节点会被父组件的作用域CSS和子的作用域CSS影响。
  • 布局时父组件样式可以影响子组件样式。这一点是第二点实现的。

深度选择器

如果你想让在scoped styles上的选择器变得"deep",例如:影响子组件,可以使用>>>连接符。

<style scoped>
.a >>> .b {/*...*/}
</style>

上面的代码会编译成:.a[data-v-f3f3eg9] .b {/* ... */}

一些预处理器,例如Sass,不能解析>>>属性。这些情况下,你使用/deep/或::v-deep连接符可以取代,这两个操作符是>>>等效的。

动态生成内容

  • 通过v-html生成的DOM内容,不会被scoped styles影响。
  • 可以通过深度选择器去渲染v-html生成的DOM内容。(>>>, /deep/, ::v-deep)

时刻提醒自己

  • 局部样式并不消除对class的需要。因为浏览器通过不同的css 选择器渲染时,例如p{color:red}在局部作用域里性能会低会慢很多。(例如与一个属性选择器连接)。如果你使用classes或者ids替代了,例如.example { color: red },其实就消除了对性能的影响。
  • 在递归组件中,小心使用后代选择器。 一个CSS规则.a .b,如果.a包括一个递归子组件,那么子组件上所有的.b都会被规则匹配到。

为什么用p会慢很多?

因为如果是元素选择器,无论是局部还是全局,浏览器需要在所有元素上搜索,几乎是从头到尾去解析,这个过程是耗性能的。而如果是类选择器或者是id选择器,只要从选择器列表中去找到即可,性能更好。

参考资料:https://vue-loader.vuejs.org/guide/scoped-css.html#mixing-local-and-global-styles

FrankKai avatar Feb 25 '20 12:02 FrankKai