导航


HTML

CSS

JavaScript

浏览器 & 网络

版本管理

框架

构建工具

TypeScript

性能优化

软实力

算法

UI、组件库

Node

业务技能

针对性攻坚

AI


一、什么是 scoped 样式穿透

scoped 样式穿透,指的是:

在 scoped 样式作用范围内,主动让样式作用到子组件内部的 DOM


scoped 默认行为

scoped 样式:

只能作用于「当前组件直接生成的 DOM」

❌ 不包括:


二、示例

Parent.vue
 └── Child.vue
      └── <div class="inner">真实 DOM</div>

Child.vue(中间组件)

<template>
  <div class="child">
    <div class="inner">I am inner dom</div>
  </div>
</template>

Parent.vue(外层组件,带 scoped)

<template>
  <Child />
</template>

<style scoped>
.inner {
  color: red;
}
</style>

上述代码表现为: .inner 不会变红


三、不会变红的原因

Vue 编译后发生了什么:

Parent.vue 编译结果(核心)

CSS 被改写为:

.inner[data-v-parent] {
  color: red;
}

Child.vue 渲染出来的真实 DOM 是:

<div class="inner" data-v-child>
  I am inner dom
</div>

❌ 匹配失败的原因

.inner[data-v-parent]
        ↑
但 DOM 上是 data-v-child

➡️ scoped 的本质限制:属性不一致,选择器不匹配


四、理解 scoped 行为

我们可以把 scoped 理解为:

“我只管我自己模板里生成的 DOM”


五、如何在 Parent 实现给 Child 设置样式


使用样式穿透

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

编译后的 CSS

[data-v-parent] .inner {
  color: red;
}

再看 DOM

<div data-v-parent>
  <div data-v-child>
    <div class="inner">I am inner dom</div>
  </div>
</div>

✅ 为什么这次能匹配?

[data-v-parent] .inner
 ↑                 ↑
 父组件根            任意后代

不再要求 .inner 自己携带 data-v-parent


六、对比总结

情况 选择器 能否命中子组件 DOM
普通 scoped .inner[data-v-parent]
样式穿透 [data-v-parent] .inner

七、slot + 真实 DOM 的情况

Parent.vue

<template>
  <Child>
    <div class="slot-inner">slot dom</div>
  </Child>
</template>

<style scoped>
.slot-inner {
  color: red;
}
</style>

Child.vue

<template>
  <div class="wrapper">
    <slot />
  </div>
</template>

问:.slot-inner 会生效吗?

👉 会生效!

为什么?

因为:


真实 DOM

<div class="slot-inner" data-v-parent>

scoped 是“按来源组件”,不是“按渲染位置”