当 <style>
标签带有 scoped
attribute 的时候,它的 CSS 只会影响当前组件的元素,和 Shadow DOM 中的样式封装类似。使用时有一些注意事项,不过好处是不需要任何的 polyfill。它的实现方式是通过 PostCSS 将以下内容:
<style scoped>
.example {
color: red;
}
</style>
<template>
<div class="example">hi</div>
</template>
转换为:
转换为:
<style>
.example[data-v-f3f3eg9] {
color: red;
}
</style>
<template>
<div class="example" data-v-f3f3eg9>hi</div>
</template>
子组件的根元素
使用 scoped
后,父组件的样式将不会渗透到子组件中。不过,子组件的根节点会同时被父组件的作用域样式和子组件的作用域样式影响。这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。
深度选择器
处于 scoped
样式中的选择器如果想要做更“深度”的选择,也即:影响到子组件,可以使用 :deep()
这个伪类:
<style scoped>
.a :deep(.b) {
/* ... */
}
</style>
上面的代码会被编译成:
.a[data-v-f3f3eg9] .b {
/* ... */
}
:::tip 通过 v-html
创建的 DOM 内容不会被作用域样式影响,但你仍然可以使用深度选择器来设置其样式。 :::
插槽选择器
默认情况下,作用域样式不会影响到 <slot/>
渲染出来的内容,因为它们被认为是父组件所持有并传递进来的。使用 :slotted
伪类以明确地将插槽内容作为选择器的目标:
<style scoped>
:slotted(div) {
color: red;
}
</style>
全局选择器
如果想让其中一个样式规则应用到全局,比起另外创建一个 <style>
,可以使用 :global
伪类来实现 (看下面的代码):
<style scoped>
:global(.red) {
color: red;
}
</style>
混合使用局部与全局样式
你也可以在同一个组件中同时包含作用域样式和非作用域样式:
<style>
/* 全局样式 */
</style>
<style scoped>
/* 局部样式 */
</style>
作用域样式须知
-
作用域样式并没有消除对 class 的需求。由于浏览器渲染各种各样 CSS 选择器的方式,
p { color: red }
结合作用域样式使用时 (即当与 attribute 选择器组合的时候) 会慢很多倍。如果你使用 class 或者 id 来替代,例如.example { color: red }
,那你几乎就可以避免性能的损失。 -
小心递归组件中的后代选择器!对于一个使用了
.a .b
选择器的样式规则来说,如果匹配到.a
的元素包含了一个递归的子组件,那么所有的在那个子组件中的.b
都会匹配到这条样式规则。
style lang=“scss” 上
加上 scoped