你不知道的原理之style标签的scoped原理(组件作用域 CSS)

前言

最近鼠鼠面试的时候,被面试官问到style标签的scoped属性原理,还好我平时在浏览器面板有注意到DOM节点多了data开头的属性,现在总结分享给大家!

原理分析

当 <style> 标签带有 scoped 属性的时候,样式只会影响当前组件的元素。它的实现方式是通过 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>
  1. 添加scoped属性之后,DOM节点添加了一个不重复的data开头的属性来表示其唯一性
  2. 添加scoped属性之后,DOM节点的css选择器末尾添加了data属性选择器来私有化该元素的样式
  3. 对于组件也是一样会添加data开头的属性来表示其唯一性

dom节点对应的样式规则添加的data开头的唯一标识是一致的!

f2af17537f8d3d4d9c9798d866f952b.png

d7d8c47986cda32fffdea20d48859c4.png

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

其它拓展

深度选择器

如果style标签添加了scoped属性,如果此时想改变子组件样式,可以使用 :deep() 这个伪类:

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

上面的代码会被编译成:

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

插槽选择器

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

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

全局选择器

如果想让其中一个样式规则应用到全局,比起另外创建一个 <style>,可以使用 :global 伪类来实现:

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

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

<style>
/* 全局样式 */
</style>

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

参考 单文件组件 CSS 功能 | Vue.js

总结

  1. 添加scoped属性之后,DOM节点添加了一个不重复的data开头的属性来表示其唯一性
  2. 添加scoped属性之后,DOM节点的css选择器末尾添加了data属性选择器来私有化该元素的样式
  3. 对于组件也是一样会添加data开头的属性来表示其唯一性
  • 27
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值