Vue 开发中为什么要使用穿透符::deep()

在 Vue 开发中,有时候样式需要穿透 才能生效,通常是因为使用了作用域样式 (scoped styles) 的缘故。


1. 什么是作用域样式 (scoped styles)?

在 Vue 单文件组件 (SFC) 中,使用 <style scoped> 声明的样式只会作用于当前组件的元素。Vue 在编译时会通过生成唯一的动态属性(如 data-v-xxxxxx)的方式,为每个组件的 DOM 节点加上标记,从而实现样式的作用域隔离。

例如:

vue 复制代码
<template>
  <div class="box">Hello</div>
</template>

<style scoped>
.box {
  color: red;
}
</style>

编译后,HTML 可能会变成:

html 复制代码
<div class="box" data-v-123abc>Hello</div>

CSS 会变成:

css 复制代码
.box[data-v-123abc] {
  color: red;
}

2. 为什么有时需要样式穿透?

有些情况下,你需要修改子组件或第三方库中的样式,这些样式可能处于另一个作用域或者被深层封装。直接在 <style scoped> 中定义样式通常无法生效,因为作用域样式只针对当前组件的 DOM 节点。

例如,想要覆盖子组件的样式:

vue 复制代码
<template>
  <child-component></child-component>
</template>

<style scoped>
/* 尝试覆盖子组件内部的样式 */
.some-class {
  color: blue;
}
</style>

以上代码不会生效,因为 .some-class 的作用域被限制在父组件,无法穿透到子组件或其内部的 DOM。


3. 如何实现样式穿透?

在 Vue 3 中,::deep() 是用于样式穿透的一种语法,替代了之前的 /deep/>>> 的用法。它允许你跨越作用域样式的限制,修改子组件或嵌套元素的样式。这样,你可以在父组件中应用样式来影响子组件的样式,尤其是当你无法直接修改子组件代码时。

::deep() 用法

::deep() 是一个 Vue 3 中的特殊选择器,用来进行样式穿透,能够影响嵌套的子组件样式。它是一个更为正式和规范的方式,代替了 Vue 2 中使用的 /deep/>>>

基本语法
vue 复制代码
<template>
  <child-component></child-component>
</template>

<style scoped>
::deep(.child-class) {
  color: red;
}
</style>

在这个例子中,::deep(.child-class) 会将 .child-class 类的样式应用到 child-component 组件内的 .child-class 元素上,即使它是在子组件中定义的,也能被父组件的样式影响。

具体解释

  • ::deep() 可以用来选择子组件内的 DOM 元素或样式,突破组件的作用域限制。
  • 它的作用类似于一个全局选择器,能够选择嵌套组件内部的元素,虽然这些元素本身是被 scoped 样式保护的。
  • ::deep() 还可以用于组合选择器、伪类、伪元素等。

例子:穿透嵌套子组件

假设有一个子组件 ChildComponent.vue,其中有一个 .btn 类的按钮样式,你希望在父组件中控制这个按钮的样式。

子组件 ChildComponent.vue

vue 复制代码
<template>
  <button class="btn">Click me</button>
</template>

<style scoped>
.btn {
  background-color: green;
  color: white;
}
</style>

父组件 ParentComponent.vue

vue 复制代码
<template>
  <child-component></child-component>
</template>

<style scoped>
::deep .btn {
  background-color: red; /* 覆盖子组件按钮的背景色 */
  color: yellow;         /* 改变文字颜色 */
}
</style>

在这个例子中,::deep .btn 会把父组件的样式应用到子组件的 .btn 按钮上,将其背景色从绿色改为红色,文字颜色改为黄色。

::deep() 的注意事项

  1. 全局影响 :虽然 ::deep() 可以穿透作用域样式,但它仍然会影响到子组件的样式,因此可能会导致子组件的样式被外部影响,破坏组件的封装性。要谨慎使用。

  2. 仅适用于 scoped 样式::deep() 主要用于作用域样式下的穿透,如果不使用 scoped,那么你就不需要使用 ::deep(),样式本来就没有作用域隔离。

  3. Vue 3 新特性::deep() 是 Vue 3 引入的语法。如果你使用的是 Vue 2,应该使用 /deep/>>>


4. 小结

在实际开发中,优先考虑保持组件样式隔离,避免直接修改子组件样式,以提高组件的可维护性和独立性。

相关推荐
辻戋2 小时前
从零实现React Scheduler调度器
前端·react.js·前端框架
徐同保2 小时前
使用yarn@4.6.0装包,项目是react+vite搭建的,项目无法启动,报错:
前端·react.js·前端框架
Qrun3 小时前
Windows11安装nvm管理node多版本
前端·vscode·react.js·ajax·npm·html5
中国lanwp3 小时前
全局 npm config 与多环境配置
前端·npm·node.js
JELEE.4 小时前
Django登录注册完整代码(图片、邮箱验证、加密)
前端·javascript·后端·python·django·bootstrap·jquery
TeleostNaCl6 小时前
解决 Chrome 无法访问网页但无痕模式下可以访问该网页 的问题
前端·网络·chrome·windows·经验分享
前端大卫7 小时前
为什么 React 中的 key 不能用索引?
前端
你的人类朋友7 小时前
【Node】手动归还主线程控制权:解决 Node.js 阻塞的一个思路
前端·后端·node.js
小李小李不讲道理9 小时前
「Ant Design 组件库探索」五:Tabs组件
前端·react.js·ant design
毕设十刻9 小时前
基于Vue的学分预警系统98k51(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js