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 仍然是静态的。自定义属性将通过内联样式应用到组件的根元素上,并在源值改变时进行响应式更新。