Vue 中的 deep 和 v-deep 区别是什么?

当你使用 Element Plus 开发了一个按钮,并尝试修改其 hover 状态下的颜色时,却遇到了样式无论如何都不生效的困扰。经过一番排查,最终发现需要添加 :deep() 选择器才能解决问题。
实际上,这是 Vue 开发中一个常见的陷阱——样式作用域冲突。那么,为什么在使用 UI 组件库时,添加了 :deep()、::v-deep 或 >>> 这些选择器后,样式就能正常生效了呢?
这些选择器究竟是什么?它们之间有什么区别?在什么情况下应该使用哪一个呢?
一、先说背景
我们在 Vue 单文件组件(.vue 文件)里写样式时,通常会加上 scoped 属性:
<template>
<el-button>点我</el-button>
</template>
<style scoped>
.el-button {
background: red;
}
</style>
加了 scoped 后,Vue 会自动给这个组件里的所有元素加上一个唯一的属性(比如 data-v-123456),然后把 CSS 选择器也加上这个属性,变成:
.el-button[data-v-123456] {
background: red;
}
这样做的好处是:样式只作用于当前组件,不会污染全局。、
但问题来了:Element Plus 的 <el-button> 组件内部结构,是在它自己的组件里定义的。也就是说,你写的 .el-button 元素,其实是 Element Plus 渲染出来的子组件,它身上没有你当前组件的 data-v-xxx 属性!
所以你的样式根本匹配不到它,自然就失效了。
二、那怎么办?
为了解决这个问题,Vue 提供了样式穿透(style penetration)的语法,让你能穿透当前组件的作用域,去影响子组件内部的元素。
Vue 社区出现过三种写法:
| 写法 | 适用版本 | 状态 |
|---|---|---|
>>> |
Vue 2(某些预处理器支持) | 已废弃/不推荐 |
::v-deep |
Vue 2 + Vue 3(兼容写法) | 过渡方案 |
:deep() |
Vue 3.0+(推荐) | 官方推荐 |
下面我们一个个拆解。
1. >>>:曾经的快捷方式,但问题很多
早期 Vue2 时代,很多人用:
<style scoped>
.parent >>> .child {
color: blue;
}
</style>
它的意思是:从 .parent 开始,穿透到所有后代中的 .child。
但问题在于:
- Sass/Less 等预处理器不认
>>>,会报错。 - 不是标准 CSS 语法。
- Vue3 已经明确不再支持。
所以现在基本可以忘掉它了。
2. ::v-deep:Vue2 到 Vue3 的桥梁
为了兼容预处理器,Vue 引入了 ::v-deep:
<style scoped lang="scss">
.parent ::v-deep(.child) {
color: blue;
}
</style>
或者更常见的写法:
.parent {
::v-deep(.child) {
color: blue;
}
}
它在 Vue2 和 Vue3 中都能用,算是一个安全的过渡方案。
但注意:在 Vue3 中,官方文档已经明确建议使用 :deep() 替代它。
3. :deep():Vue3 的标准答案
Vue3 引入了更简洁、更符合 CSS 规范的伪类函数写法:
<style scoped>
:deep(.el-button) {
background: red !important;
}
</style>
或者配合父级选择器:
<style scoped>
.my-wrapper :deep(.el-input__inner) {
border-radius: 10px;
}
</style>
优点:
- 语法清晰,像原生 CSS。
- 支持所有预处理器(Sass/Less/Stylus)。
:deep() 本质上是一个编译时转换,Vue 在构建时会把它展开成带 data-v-xxx 的复杂选择器,从而实现穿透。
三、怎么正确修改 Element Plus 的样式?
举个真实例子:你想把 Element Plus 的输入框圆角改成 8px。
错误写法(不生效):
<style scoped>
.el-input__inner {
border-radius: 8px;
}
</style>
正确写法:
<template>
<div class="my-form">
<el-input v-model="value" />
</div>
</template>
<style scoped>
.my-form :deep(.el-input__inner) {
border-radius: 8px;
}
</style>
为什么要加 .my-form 这个父级?
避免全局污染!如果直接写 :deep(.el-input__inner),那么这个页面里所有 Element 输入框都会被改掉。加上父级限定,就能够精准的控制范围。
以上关于Vue 中的 deep 和 v-deep 区别是什么?的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » Vue 中的 deep 和 v-deep 区别是什么?

微信
支付宝