:deep() 是 Vue3 官方推荐的深度选择器,::v-deep 是过渡期别名且已弃用,>>> 在 SCSS 中因语法冲突失效;穿透仅作用于子组件内部深层 DOM,根节点无需穿透。

::v-deep 和 :deep() 是当前 Vue3 + SCSS 场景下唯一可靠的选择,/deep/ 会报错,>>> 在多数构建工具中已失效。
SCSS 中 >>> 为什么总是不生效
SCSS 预处理器在解析时会把 >>> 当作嵌套操作符(类似 &),而不是 Vue 的深度选择器语法,导致编译阶段直接丢弃或报错。Vite、Vue CLI 5+、@vitejs/plugin-vue 等主流工具链默认不支持该写法,且无 fallback 行为。
常见错误现象:.a >>> .b { color: red; } 编译后完全消失,控制台无警告,样式也不生效。
- 不要依赖
>>>—— 它不是标准 CSS,也不是 SCSS 原生语法,纯属历史兼容产物 - 即使局部生效,也大概率是构建工具偶然未拦截,不可移植
- 若项目用了 Sass(.sass 语法),
>>>更可能被解析成“父选择器右移”而报错
:deep() 是 Vue3 官方推荐的穿透语法
:deep() 是 Vue 官方在 v3.2+ 明确引入的伪类函数,由 Vue 编译器识别并处理,不会经过 SCSS 解析器,因此与预处理器完全解耦。
立即学习“前端免费学习笔记(深入)”;
使用场景:需要修改第三方 UI 组件(如 Element Plus、Ant Design Vue)内部子元素样式,同时保留 scoped 隔离性。
- 必须写在选择器内部,例如:
:deep(.el-input__inner) { border-radius: 4px; } - 可嵌套使用:
.my-form :deep(.el-input) :deep(.el-input__inner) { padding: 0 12px; } - 不能省略括号,
:deep .el-input__inner是无效写法,会被忽略 - 搭配 SCSS 变量或嵌套完全正常:
.card { :deep(.el-button) { color: $primary-color; } }
::v-deep 在某些旧版构建配置中仍可工作,但有警告
::v-deep 是 Vue2 向 Vue3 过渡期的别名写法,目前仍被大多数工具支持,但 Vite 4.3+ 和 vue-loader 17.4+ 会输出警告::v-deep usage as a combinator has been deprecated. Use :deep() instead.
它的问题在于语义模糊:作为伪元素还是伪类?不同 loader 解析逻辑不一致,容易在升级后突然失效。
- 写法上必须带空格:
::v-deep .el-checkbox__label,紧贴(如::v-deep.el-checkbox__label)会失效 - 在
lang="scss"下可用,但和:deep()相比无额外优势 - 若团队已统一用 Vite + Vue3,建议立刻迁移到
:deep(),避免未来构建失败
真正容易被忽略的点:穿透只作用于子组件内部,不作用于根节点
scoped 样式天然能命中第三方组件的**根元素**(因为 Vue 会给子组件根标签自动添加 data-v-xxx),所以改根样式根本不需要穿透。比如想调 .el-dialog 的宽高,直接写 .el-dialog { width: 500px; } 就行。
穿透真正要解决的,是子组件内部的“深层 DOM”,比如 .el-dialog__body、.el-table__row 这类非根节点——它们由子组件自己渲染,不带当前组件的 data-v-xxx,才需要 :deep() 放行。
换句话说:先确认你改的是不是根节点;如果不是,再加 :deep();如果是,加了反而多余,还可能因选择器权重变低而被覆盖。


















