单文件组件 CSS 功能
组件作用域 CSS
当
<style>
标签带有
scoped
attribute 的时候,它的 CSS 只会影响当前组件的元素,和 Shadow DOM 中的样式封装类似。使用时有一些注意事项,不过好处是不需要任何的 polyfill。它的实现方式是通过 PostCSS 将以下内容:
转换为:
子组件的根元素
使用
scoped
后,父组件的样式将不会渗透到子组件中。不过,子组件的根节点会同时被父组件的作用域样式和子组件的作用域样式影响。这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。
深度选择器
处于
scoped
样式中的选择器如果想要做更“深度”的选择,也即:影响到子组件,可以使用
:deep()
这个伪类:
上面的代码会被编译成:
TIP
通过
v-html
创建的 DOM 内容不会被作用域样式影响,但你仍然可以使用深度选择器来设置其样式。
插槽选择器
默认情况下,作用域样式不会影响到
<slot/>
渲染出来的内容,因为它们被认为是父组件所持有并传递进来的。使用
:slotted
伪类以明确地将插槽内容作为选择器的目标:
全局选择器
如果想让其中一个样式规则应用到全局,比起另外创建一个
<style>
,可以使用
:global
伪类来实现 (看下面的代码):
混合使用局部与全局样式
你也可以在同一个组件中同时包含作用域样式和非作用域样式:
作用域样式须知
-
作用域样式并没有消除对 class 的需求 。由于浏览器渲染各种各样 CSS 选择器的方式,
p { color: red }
结合作用域样式使用时 (即当与 attribute 选择器组合的时候) 会慢很多倍。如果你使用 class 或者 id 来替代,例如.example { color: red }
,那你几乎就可以避免性能的损失。 -
小心递归组件中的后代选择器 !对于一个使用了
.a .b
选择器的样式规则来说,如果匹配到.a
的元素包含了一个递归的子组件,那么所有的在那个子组件中的.b
都会匹配到这条样式规则。
CSS Modules
一个
<style module>
标签会被编译为
CSS Modules
并且将生成的 CSS class 作为
$style
对象暴露给组件:
得出的 class 将被哈希化以避免冲突,实现了同样的将 CSS 仅作用于当前组件的效果。
参考 CSS Modules spec 以查看更多详情,例如 global exceptions 和 composition 。
自定义注入名称
你可以通过给
module
attribute 一个值来自定义注入 class 对象的属性名:
与组合式 API 一同使用
可以通过
useCssModule
API 在
setup()
和
<script setup>
中访问注入的 class。对于使用了自定义注入名称的
<style module>
块,
useCssModule
接收一个匹配的
module
attribute 值作为第一个参数:
CSS 中的
v-bind()
单文件组件的
<style>
标签支持使用
v-bind
CSS 函数将 CSS 的值链接到动态的组件状态:
这个语法同样也适用于
<script setup>
,且支持 JavaScript 表达式 (需要用引号包裹起来):