标准答案
- scoped CSS 会在编译时给当前组件模板节点加上类似 data-v-xxxx 的属性,并把样式选择器也改写成带这个属性的形式。
- 它能减少当前组件样式泄漏到其它组件,但不是 Shadow DOM,仍然会受到全局样式、继承属性和子组件根节点影响。
- :deep() 用来穿透到子组件内部元素,适合覆盖组件库内部样式,但要控制范围。
- :slotted() 用来选择插槽传入内容,适合组件要约束 slot 内容外观的场景。
- :global() 用来在 scoped 块里声明全局样式,应该少用,并且命名要避免污染。
题目解析
scoped 的本质是选择器改写,不是运行时样式隔离。
deep 选择器越宽,越容易打破组件封装。二次封装组件库时应优先用组件提供的 class、变量或 API。
插槽内容属于父组件作用域。要影响插槽内容时,普通 scoped 选择器不一定能命中,需要理解 slotted 的边界。
代码示例
下面展示 scoped、deep 和 global 的典型写法。
Vue
<template>
<section class="panel">
<ThirdPartyTable />
</section>
</template>
<style scoped>
.panel {
padding: 16px;
}
:deep(.third-party-table__header) {
font-weight: 600;
}
:global(.app-lock-scroll) {
overflow: hidden;
}
</style>常见误区
- 以为 scoped CSS 能完全隔离样式,不会受到任何全局样式影响。
- 大量使用 :deep() 覆盖组件库内部结构,组件库升级后样式容易失效。
- 在 scoped 里随意写 :global(),导致全站样式污染。