仪菁菁 發表於 2026-2-3 11:03:00

Vue 中的 deep、v-deep 和 >>> 有什么区别?什么时候该用?

<h1 data-id="heading-0">🧑‍💻 写在开头</h1>
<p>点赞 + 收藏 === 学会🤣🤣🤣</p>
<div>
<div>
<p>“你用 <code>Element Plus</code> 写了个按钮,想改下 hover 颜色,结果死活不生效!最后查了半天,发现得加个 <code>:deep()</code> 才行”</p>
<p>其实,这是 Vue 中一个非常常见的坑:<strong>样式作用域冲突</strong>。那为什么用 UI 库时,加上 <code>:deep()</code>、<code>::v-deep</code> 或 <code>&gt;&gt;&gt;</code>后,样式就能生效呢?</p>
<p>它们是什么?有什么区别?什么时候该用哪个?</p>
<h2 data-id="heading-0">一、先说背景</h2>
<p>我们在 Vue 单文件组件(<code>.vue</code> 文件)里写样式时,通常会加上 <code>scoped</code> 属性:</p>
</div>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">&lt;template&gt;
&lt;el-button&gt;点我&lt;/el-button&gt;
&lt;/template&gt;

&lt;style scoped&gt;
.el-button {
background: red;
}
&lt;/style&gt;</pre>
</div>
<p>加了&nbsp;<code>scoped</code>&nbsp;后,Vue 会自动给这个组件里的所有元素加上一个唯一的属性(比如&nbsp;<code>data-v-123456</code>),然后把 CSS 选择器也加上这个属性,变成:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">.el-button {
background: red;
}</pre>
</div>
<div>
<div>
<p>这样做的好处是:<strong>样式只作用于当前组件,不会污染全局</strong>。、</p>
<p>但问题来了:<strong>Element Plus 的 <code>&lt;el-button&gt;</code> 组件内部结构,是在它自己的组件里定义的</strong>。也就是说,你写的 <code>.el-button</code> 元素,其实是 Element Plus 渲染出来的子组件,它身上<strong>没有</strong>你当前组件的 <code>data-v-xxx</code> 属性!</p>
<p>所以你的样式根本匹配不到它,自然就失效了。</p>
<hr>
<h2 data-id="heading-1">二、那怎么办?</h2>
<p>为了解决这个问题,Vue 提供了样式穿透(style penetration)的语法,让你能穿透当前组件的作用域,去影响子组件内部的元素。</p>
<p>Vue 社区出现过三种写法:</p>
</div>
<p><img src="https://img2024.cnblogs.com/blog/2149129/202602/2149129-20260203110116230-1515897704.png" alt="ScreenShot_2026-02-03_105557_840" loading="lazy"></p>
<p>下面我们一个个拆解。</p>
<hr>
<h3 data-id="heading-2">1.&nbsp;<code>&gt;&gt;&gt;</code>:曾经的快捷方式,但问题很多</h3>
<p>早期 Vue2 时代,很多人用:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">&lt;style scoped&gt;
.parent &gt;&gt;&gt; .child {
color: blue;
}
&lt;/style&gt;</pre>
</div>
<div>
<div>
<p>它的意思是:从 <code>.parent</code> 开始,穿透到所有后代中的 <code>.child</code>。</p>
<p>但问题在于:</p>
<ul>
<li><strong>Sass/Less 等预处理器不认 <code>&gt;&gt;&gt;</code></strong>,会报错。</li>
<li>不是标准 CSS 语法。</li>
<li>Vue3 已经明确不再支持。</li>
</ul>
<p>所以现在基本可以忘掉它了。</p>
<hr>
<h3 data-id="heading-3">2. <code>::v-deep</code>:Vue2 到 Vue3 的桥梁</h3>
<p>为了兼容预处理器,Vue 引入了 <code>::v-deep</code>:</p>
</div>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">&lt;style scoped lang="scss"&gt;
.parent ::v-deep(.child) {
color: blue;
}
&lt;/style&gt;</pre>
</div>
<p>或者更常见的写法:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">.parent {
::v-deep(.child) {
    color: blue;
}
}</pre>
</div>
<p>它在 Vue2 和 Vue3 中都能用,算是一个安全的过渡方案。</p>
<p>但注意:在 Vue3 中,官方文档已经明确建议使用&nbsp;<code>:deep()</code>&nbsp;替代它。</p>
<hr>
<h3 data-id="heading-4">3.&nbsp;<code>:deep()</code>:Vue3 的标准答案</h3>
<p>Vue3 引入了更简洁、更符合 CSS 规范的伪类函数写法:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">&lt;style scoped&gt;
:deep(.el-button) {
background: red !important;
}
&lt;/style&gt;</pre>
</div>
<p>或者配合父级选择器:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">&lt;style scoped&gt;
.my-wrapper :deep(.el-input__inner) {
border-radius: 10px;
}
&lt;/style&gt;</pre>
</div>
<div>
<div>
<p><strong>优点</strong>:</p>
<ul>
<li>语法清晰,像原生 CSS。</li>
<li>支持所有预处理器(Sass/Less/Stylus)。</li>
</ul>
<p><code>:deep()</code> 本质上是一个编译时转换,Vue 在构建时会把它展开成带 <code>data-v-xxx</code> 的复杂选择器,从而实现穿透。</p>
<hr>
<h2 data-id="heading-5">三、怎么正确修改 Element Plus 的样式?</h2>
<p>举个真实例子:你想把 Element Plus 的输入框圆角改成 8px。</p>
<h3 data-id="heading-6">错误写法(不生效):</h3>
</div>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">&lt;style scoped&gt;
.el-input__inner {
border-radius: 8px;
}
&lt;/style&gt;</pre>
</div>
<h3 data-id="heading-7">正确写法:</h3>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">&lt;template&gt;
&lt;div class="my-form"&gt;
    &lt;el-input v-model="value" /&gt;
&lt;/div&gt;
&lt;/template&gt;

&lt;style scoped&gt;
.my-form :deep(.el-input__inner) {
border-radius: 8px;
}
&lt;/style&gt;</pre>
</div>
<p>为什么要加&nbsp;<code>.my-form</code>&nbsp;这个父级?</p>
<p><em id="__mceDel">避免全局污染!如果直接写&nbsp;<code>:deep(.el-input__inner)</code>,那么这个页面里所有&nbsp;Element 输入框都会被改掉。加上父级限定,就能精准控制范围。</em></p>
<div>
<h3 id="tid-D8HBxE">如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。</h3>
</div>
<p><em><img src="https://img2024.cnblogs.com/blog/2149129/202501/2149129-20250122165814748-630765389.png" alt="" loading="lazy"></em></p>
</div>
</div>
</div>
</div><br><br>
来源:https://www.cnblogs.com/smileZAZ/p/19568039
頁: [1]
查看完整版本: Vue 中的 deep、v-deep 和 >>> 有什么区别?什么时候该用?