2
0
积极分子
点赞 + 收藏 === 学会🤣🤣🤣
“你用 Element Plus 写了个按钮,想改下 hover 颜色,结果死活不生效!最后查了半天,发现得加个 :deep() 才行”
Element Plus
:deep()
其实,这是 Vue 中一个非常常见的坑:样式作用域冲突。那为什么用 UI 库时,加上 :deep()、::v-deep 或 >>>后,样式就能生效呢?
::v-deep
>>>
它们是什么?有什么区别?什么时候该用哪个?
我们在 Vue 单文件组件(.vue 文件)里写样式时,通常会加上 scoped 属性:
.vue
scoped
<template> <el-button>点我</el-button> </template> <style scoped> .el-button { background: red; } </style>
加了 scoped 后,Vue 会自动给这个组件里的所有元素加上一个唯一的属性(比如 data-v-123456),然后把 CSS 选择器也加上这个属性,变成:
data-v-123456
.el-button[data-v-123456] { background: red; }
这样做的好处是:样式只作用于当前组件,不会污染全局。、
但问题来了:Element Plus 的 <el-button> 组件内部结构,是在它自己的组件里定义的。也就是说,你写的 .el-button 元素,其实是 Element Plus 渲染出来的子组件,它身上没有你当前组件的 data-v-xxx 属性!
<el-button>
.el-button
data-v-xxx
所以你的样式根本匹配不到它,自然就失效了。
为了解决这个问题,Vue 提供了样式穿透(style penetration)的语法,让你能穿透当前组件的作用域,去影响子组件内部的元素。
Vue 社区出现过三种写法:
下面我们一个个拆解。
早期 Vue2 时代,很多人用:
<style scoped> .parent >>> .child { color: blue; } </style>
它的意思是:从 .parent 开始,穿透到所有后代中的 .child。
.parent
.child
但问题在于:
所以现在基本可以忘掉它了。
为了兼容预处理器,Vue 引入了 ::v-deep:
<style scoped lang="scss"> .parent ::v-deep(.child) { color: blue; } </style>
或者更常见的写法:
.parent { ::v-deep(.child) { color: blue; } }
它在 Vue2 和 Vue3 中都能用,算是一个安全的过渡方案。
但注意:在 Vue3 中,官方文档已经明确建议使用 :deep() 替代它。
Vue3 引入了更简洁、更符合 CSS 规范的伪类函数写法:
<style scoped> :deep(.el-button) { background: red !important; } </style>
或者配合父级选择器:
<style scoped> .my-wrapper :deep(.el-input__inner) { border-radius: 10px; } </style>
优点:
:deep() 本质上是一个编译时转换,Vue 在构建时会把它展开成带 data-v-xxx 的复杂选择器,从而实现穿透。
举个真实例子:你想把 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 这个父级?
.my-form
避免全局污染!如果直接写 :deep(.el-input__inner),那么这个页面里所有 Element 输入框都会被改掉。加上父级限定,就能精准控制范围。
:deep(.el-input__inner)
使用道具 举报
本版积分规则 发表回复 回帖并转播 回帖后跳转到最后一页
相关侵权、举报、投诉及建议等,请发 E-mail:qiongdian@foxmail.com
Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.