跳转到内容

SFC CSS功能

作用域CSS

<style>标签有scoped属性时,其CSS将只应用于当前组件的元素。这类似于在Shadow DOM中找到的风格封装。它有一些注意事项,但不需要任何polyfills。它通过使用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>

子组件根元素

使用 scoped 时,父组件的样式不会泄露到子组件中。然而,子组件的根节点将同时受到父组件的 scoped CSS 和子组件本身的 scoped CSS 的影响。这是有意为之,以便父组件可以为布局目的对子组件的根元素进行样式化。

深度选择器

如果您想让 scoped 样式中的选择器“深度”有效,即影响子组件,可以使用 :deep() 伪类。

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

以上将编译成

CSS
.a[data-v-f3f3eg9] .b {
  /* ... */
}

提示

使用 v-html 创建的 DOM 内容不受 scoped 样式的影响,但您仍然可以使用深度选择器来对它们进行样式化。

插槽选择器

默认情况下,scoped 样式不会影响由 <slot/> 渲染的内容,因为它们被视为由传入父组件拥有的。为了显式地针对插槽内容,请使用 :slotted 伪类。

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

全局选择器

如果您只想让一条规则全局应用,您可以使用 :global 伪类,而不是创建另一个 <style>(见下文)。

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

混合局部和全局样式

您还可以在同一组件中包含 scoped 和非 scoped 样式。

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

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

Scoped 样式提示

  • Scoped 样式并不能消除对类的需求。 由于浏览器渲染各种 CSS 选择器的不同方式,当 scoped(即与属性选择器结合时)时,p { color: red } 将变得非常慢。如果您使用类或 id(如 .example { color: red }),则几乎可以消除这种性能损失。

  • 在递归组件中要小心使用后代选择器! 对于具有选择器 .a .b 的 CSS 规则,如果匹配 .a 的元素包含一个递归子组件,则该子组件中的所有 .b 都将匹配该规则。

CSS 模块

<style module> 标签会被编译为 CSS Modules,并将生成的 CSS 类作为对象暴露给组件,该对象在 $style 键下。

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

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

生成的类经过哈希处理以避免冲突,从而实现了将 CSS 作用域限制为当前组件的效果。

有关更多信息,例如 全局异常组合,请参阅 CSS Modules 规范

自定义注入名称

您可以通过给 module 属性赋值来自定义注入类的对象属性键。

vue
<template>
  <p :class="classes.red">red</p>
</template>

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

与组合 API 一起使用

可以通过 useCssModule API 在 setup()<script setup> 中访问注入的类。对于具有自定义注入名称的 <style module> 块,useCssModule 接受匹配的 module 属性值作为第一个参数。

js
import { useCssModule } from 'vue'

// inside setup() scope...
// default, returns classes for <style module>
useCssModule()

// named, returns classes for <style module="classes">
useCssModule('classes')
  • 示例
vue
<script setup lang="ts">
import { useCssModule } from 'vue'

const classes = useCssModule()
</script>

<template>
  <p :class="classes.red">red</p>
</template>

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

CSS 中的 v-bind()

SFC <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>

该语法与 <script setup> 一起使用,并支持 JavaScript 表达式(必须用引号括起来)。

vue
<script setup>
import { ref } from 'vue'
const theme = ref({
    color: 'red',
})
</script>

<template>
  <p>hello</p>
</template>

<style scoped>
p {
  color: v-bind('theme.color');
}
</style>

实际值将被编译成哈希过的 CSS 自定义属性,因此 CSS 仍然是静态的。自定义属性将通过内联样式应用到组件的根元素上,并在源值改变时进行响应式更新。

SFC CSS 功能已加载