为什么需要样式穿透
当我们创建私有组件时(组件样式标签添加scoped),引用了子组件或 UI 组件,你会发现在我们私有组件并不能直接修改其样式。遇到这种情况,一般有两种解决方式:一是添加全局样式(需要覆盖全局样式时);再者就是样式穿透了(组件样式)。
样式穿透的三种方式
以下三种方式在 Vue3 中均已弃用,详见 Vue3 组件样式变化。
>>>:适用于css、stylus/deep/:适用于node-sass、less::v-deep:适用于dart-sass、node-sass、less、stylus
1 | <!-- >>> 用法 --> |
Vue3 组件样式变化
根据 Vue 的 RFC 文件(意见征求稿)中,以上三种样式穿透方式都已被弃用,将用::v-deep() 简写 :deep() 替代。官方文件详情 => 私有样式改变 RFC。

文稿中大致意思是,最初使用的深度选择器是 >>> ,但某些 CSS 预编译器解析时存在问题,后来切换到 /deep/,曾经添加到 CSS 标准提议 中,后被放弃,为了避免混淆又引入了自定义的组合器 ::v-deep。为了兼容性,vue2 中才保留了其他两种。
在开发新的 vue3 SFC 编译器时,我们注意到 CSS 伪元素实际在语义上不是组合器,伪元素接受参数更符合惯用的 CSS,所以采用了 ::v-deep() 替换,简写 :deep()。
注:截止 2022 年 5 月 以上 3 种旧的深度选择器任能在 vue3 项目中使用,但会有警告提示信息;

另外 Vue3 中还添加了另外两个伪元素 ::v-slotted() 和 ::v-global()。总结如下:
::v-deep()简写:deep():深度选择器(样式穿透);::v-slotted()简写:slotted():插槽选择器;Vue3 默认情况下,作用域样式不会影响到
<slot/>渲染出来的内容,因为它们被认为是父组件所持有并传递进来的。使用:slotted()伪类以确切地将插槽内容作为选择器的目标。::global()简写:global():全局选择器;如果想让其中一个样式规则应用到全局,比起另外创建一个
<style>,可以使用:global()伪类来实现。
1 | <style scoped> |



