Vue深度选择器 ::v-deep、 :deep()

909 阅读3分钟

Vue2的::v-deep和Vue3的:deep()有什么区别

github.com/vuejs/rfcs/…

Vue3开发新的SFC编译器时,注意到CSS伪元素实际上在语义上不是组合。伪元素接受参数更符合习惯用法,因此可以使用::v-deep()的方式,即之前的::v-deep加()。还可以使用更简短:deep()的方式,它们的工作方式都是一样的。

Vue3的 :deep()伪类

:deep()定义

:deep()是一个伪类,它可以使处在scoped样式中的选择器影响到子组件。

使用scoped后,父组件的样式将不会渗透到子组件。

不过,子组件的根节点会同时被父组件的作用域样式和子组件的作用域样式影响。

这样设计是为了让父组件可以从布局的角度出发,调整其子节点根元素的样式。

:deep()测试案例

父组件:

<template>
    <div class="page">
        <div class="father-box">我是父组件</div>
        <VueCSSDeepSon></VueCSSDeepSon>
    </div>
</template>

<script setup lang="ts">
import VueCSSDeepSon from './VueCSSDeepSon.vue'
</script>

<style scoped>
.page .father-box{
    color: black;
}
.page:deep(.son-box) {
    color: red;
}
.page .son-box {
    background-color: green;
}
</style>

子组件:

<template>
   <div>
        <div class="son-box">我是子组件</div>
   </div>
</template>

<script setup lang="ts">
</script>

<style scoped>
.son-box {
    color: yellow;
}
</style>

最终渲染截图: image.png

延伸知识

数据属性(data-*)

data-*属性允许我们在标准/语义化的HTML元素中存储额外的信息, 而不需要使用类似于非标准属性或者DOM额外属性之类的技巧。

所有在元素上以data-*开头的属性为数据属性。

CSS的属性选择器

上述截图中的.page[data-v-5a282b66]即匹配带有一个名为data-v-5a282b66的属性且类名为page的元素

延伸:CSS的选择器
选择器的种类

developer.mozilla.org/zh-CN/docs/…

  • 全局选择器(*)
  • 类型、类和ID选择器
  • 标签属性选择器

(1)存否和值选择器

[attr] a[data-*]

[attr=value] a[href="example.com"]

[attr~=vakue] p[class~="special"]

<template>
    <div>
        <div class="a">aaa</div>
        <div class="a b">aaa bbb</div>
        <div class="c">ccc</div>
        <div>ddd</div>
    </div>
</template>

<style scoped>
div {
    border-right: 10px solid blue;
}
div[class] {
    border-left: 10px solid green;
}
div[class='a'] {
    background: yellow;
}
div[class~="a"] {
    color: red;
}
</style>

image.png (2) 子字符串匹配选择器

[attr^=value] 值开头为value子字符串

[attr$=value] 值结尾为value子字符串

[attr*=value] 值的字符串中任何地方,至少出现了一次value子字符串

  • 伪类与伪元素

    伪类是选择器的一种,它用于选择处于特定状态的元素。

    伪元素以类似的方式表示,不过表现得像你往标注文本中加入全新的HTML元素一样,而不是向现有的元素上应用类。伪元素开头为双冒号::

  • 关系选择器/运算符

  1. 后代选择器 (" ")空格
  2. 子代关系选择器 (>) 大于号
  3. 邻接兄弟 (+) 加号
  4. 通用兄弟 (~)

Vue是如何实现组件CSS作用域的?

  1. Vue通过PostCSS为一个组件的每个节点增加一个独有的数据属性。同一个组件上所有节点数据属性相同,不同组件的数据属性不同。

  2. <style>标签带有scoped attribute的时候,css选择器尾部都添加上这个属性选择器,从而实现了CSS只会影响当前组件的元素。

从上述案例截图发现,组件的根节点上有当前组件的数据属性,还有父组件的数据属性。所以根节点会同时被父组件的作用域样式和子组件的作用域样式影响。除了根节点,子组件的其他节点则需要通过:deep()伪类来实现。

Vue2的::v-deep

官方文档地址:vue-loader.vuejs.org/zh/guide/sc…

深度作用选择器

有些像Sass之类的预处理器无法解析>>>。这种情况下可以使用/deep/或者::v-deep操作符取而代之————两者都是>>>的别名,同样可以正常工作。

.a::v-deep .b {
    background-color: yellow;
}

deep的原理

deep的原理就是将私有属性移到上一层

加上deep深度选择器后,deep内的class都没有加私有属性,而是把私有属性提升到了deep的上一层。