scoped css通过编译时为元素添加唯一data-v-xxx属性并改写选择器(如.btn→.btn[data-v-xxx])实现样式隔离;子组件因拥有独立属性值而不匹配父组件规则;深度选择器:deep()或::v-deep使后续选择器取消属性限制,实现穿透。

Scoped CSS 的核心是让样式只作用于当前组件,不污染全局,也不被外部干扰。它靠的是编译时自动加属性标识,而不是运行时动态控制。
Scoped 样式怎么实现隔离
Vue 在编译单文件组件时,会做两件事:
- 给组件的根元素(以及所有子节点中由当前模板直接渲染的元素)添加一个唯一属性,比如 data-v-f3f3eg9
- 把
<style scoped></style>里的每个选择器,都自动补上这个属性条件。例如.btn变成.btn[data-v-f3f3eg9]
这样浏览器只会匹配同时满足「有 .btn 类」且「有 data-v-f3f3eg9 属性」的元素,自然就锁死在本组件内。
为什么子组件样式不受影响
因为子组件的根元素虽然被父组件模板包含,但它自己也有独立的 data-v-xxxx 属性(来自它自己的 scoped 样式)。父组件的样式规则里没有匹配子组件那个哈希值,所以不会生效。
比如父组件生成的是 .title[data-v-a1b2],而子组件元素带的是 data-v-c3d4,两者对不上,样式就穿不透。
深度选择器是怎么打破隔离的
深度选择器不是“绕过” scoped,而是告诉编译器:「这条规则里,后面那段选择器不要加 data-v-xxx」。
-
::v-deep .icon(Vue 2)或:deep(.icon)(Vue 3)会让.icon部分保持原样,不加属性限制 - 最终编译结果类似:
.parent[data-v-a1b2] .icon—— 前半段仍受控,后半段自由匹配
所以它能选中子组件内部带 .icon 类的元素,哪怕那个元素属于另一个组件。
常见写法和注意事项
三种写法本质等价,但兼容性不同:
-
>>>(空格前缀,已废弃,部分构建工具不支持) -
/deep/(Vue 2 推荐,但某些 loader 已弃用) -
::v-deep(Vue 2.6+)或:deep()(Vue 3)—— 官方推荐,语义清晰
注意:深度选择器只对它后面的那部分选择器取消 scoped 限制,前面的父选择器依然带 data-v-xxx,确保不会误击其他组件。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











