知海

单文件组件 CSS 功能

VueAPI 参考

单文件组件 CSS 功能 {#sfc-css-features}

组件作用域 CSS {#scoped-css}

<style> 标签带有 scoped 属性时,其 CSS 只会影响当前组件的元素,这与 Shadow DOM 中的样式封装类似。使用时需要注意一些事项,但优点是不需要任何 polyfill。

实现原理是通过 PostCSS 将以下代码:

vue 复制代码
<style scoped>
.example {
  color: red;
}
</style>

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

转换为:

vue 复制代码
<style>
.example[data-v-f3f3eg9] {
  color: red;
}
</style>

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

子组件的根元素 {#child-component-root-elements}

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

深度选择器 {#deep-selectors}

scoped 样式中,如果需要对子组件进行更深层次的选择,可以使用 :deep() 这个伪类:

vue 复制代码
<style scoped>
.a :deep(.b) {
  /* ... */
}
</style>

上述代码会被编译为:

css 复制代码
.a[data-v-f3f3eg9] .b {
  /* ... */
}

💡 提示
通过 v-html 创建的 DOM 内容不会被作用域样式影响,但你仍然可以使用深度选择器来设置其样式。

插槽选择器 {#slotted-selectors}

默认情况下,作用域样式不会影响 <slot/> 渲染出来的内容,因为它们被认为是父组件所持有并传递进来的。使用 :slotted 伪类可以明确地将插槽内容作为选择器的目标:

vue 复制代码
<style scoped>
:slotted(div) {
  color: red;
}
</style>

全局选择器 {#global-selectors}

如果希望某个样式规则应用到全局,除了单独创建一个 <style> 标签外,也可以使用 :global 伪类来实现:

vue 复制代码
<style scoped>
:global(.red) {
  color: red;
}
</style>

混合使用局部与全局样式 {#mixing-local-and-global-styles}

你也可以在同一个组件中同时包含作用域样式和非作用域样式:

vue 复制代码
<style>
/* 全局样式 */
</style>

<style scoped>
/* 局部样式 */
</style>

作用域样式须知 {#scoped-style-tips}

  • 作用域样式并不能消除对 class 的需求。由于浏览器渲染各种 CSS 选择器的方式,p { color: red } 结合作用域样式使用时(即与属性选择器组合时)会慢很多倍。如果使用 class 或 id 来替代,例如 .example { color: red },则可以基本避免性能损失。

  • 小心递归组件中的后代选择器!对于使用了 .a .b 选择器的样式规则,如果匹配到 .a 的元素包含了一个递归的子组件,那么该子组件中所有的 .b 都会被匹配到这条样式规则。

CSS Modules {#css-modules}

一个 <style module> 标签会被编译为 CSS Modules,并将生成的 CSS class 作为 $style 对象暴露给组件:

vue 复制代码
<template>
  <p :class="$style.red">This should be red</p>
</template>

<style module>
.red {
  color: red;
}
</style>

生成的 class 会被哈希化以避免冲突,实现了将 CSS 仅作用于当前组件的效果。

参考 CSS Modules 规范 以查看更多详情,例如 全局例外组合

自定义注入名称 {#custom-inject-name}

你可以通过给 module 属性传入一个值来自定义注入 class 对象的属性名:

vue 复制代码
<template>
  <p :class="classes.red">red</p>
</template>

<style module="classes">
.red {
  color: red;
}
</style>

与组合式 API 一同使用 {#usage-with-composition-api}

可以通过 useCssModule API 在 setup() 和 `

复制代码
## CSS 中的 `v-bind()` {#v-bind-in-css}

单文件组件的 `<style>` 标签支持使用 `v-bind` CSS 函数将 CSS 的值链接到动态的组件状态:

```vue
<template>
  <div class="text">hello</div>
</template>

<script>
export default {
  data() {
    return {
      color: 'red'
    }
  }
}
</script>

<style>
.text {
  color: v-bind(color);
}
</style>

这个语法同样也适用于 [`

复制代码
实际的值会被编译成哈希化的 CSS 自定义属性,因此 CSS 本身仍然是静态的。自定义属性会通过内联样式的方式应用到组件的根元素上,并且在源值变更时响应式地更新。

帮助我们改进文档

发现翻译问题或内容错误?请告诉我们。