TAY
笔记 · · 阅读 82

Vue3 深度选择器:deep()、插槽选择器:slotted()、全局选择器 :global()

在Vue中,除了常见的CSS选择器外,还有一些独有的选择器,这些选择器可以更方便地操作Vue组件。
scoped原理:

在Vue组件中,如果使用了scoped样式,子组件样式将不会被渲染到父组件中。 scoped 通过在DOM结构以及css样式上加唯一不重复的标记:data-v-hash的方式,以保证唯一(而这个工作是由过PostCSS 转译实现的),达到样式私有化模块化的目的。

当 <style> 标签带有 scoped 的时候,它的 CSS 只会影响当前组件的元素,它的实现方式是通过 PostCSS 将以下内容:

<style scoped>
.example {
  color: red;
}
</style>
 
<template>
  <div class="example">hi</div>
</template>

转换为:

<style>
.example[data-v-f3f3eg9] {
  color: red;
}
</style>
 
<template>
  <div class="example" data-v-f3f3eg9>hi</div>
</template>

总结一下scoped三条渲染规则:

给HTML的DOM节点加一个不重复data属性(形如:data-v-123)来表示他的唯一性
在每句css选择器的末尾(编译后的生成的css语句)加一个当前组件的data属性选择器(如[data-v-123])来私有化样式
如果组件内部包含有其他组件,只会给其他组件的最外层标签加上当前组件的data属性

1、深度选择器 :deep()

处于 scoped 样式中的选择器如果想要做更“深度”的选择,也即:影响到子组件,可以使用 :deep() 这个伪类:

作用:深度选择器可以匹配组件中嵌套的子组件。

常见作用场景:修改组件库样式

使用示例:

<template>
  <div>
    <div class="parent">
        <el-input></el-input>
  </div>
</template>
 
<style scoped>
  /* 选择子组件中的元素 */
  .parent :deep(.el-input__inner) {
    background: red;
  }
/* 此时css解析的为 .outer[data-v-xxxx] .el-input__inner 样式生效 */
</style>

上面的代码会被编译成:

.parent[data-v-f3f3eg9] .el-input__inner {
  background: red;
}

TIP!!!

通过 v-html 创建的 DOM 内容不会被作用域样式影响,但你仍然可以使用深度选择器来设置其样式。

2、插槽选择器 :slotted()

默认情况下,作用域样式不会影响到 <slot/> 渲染出来的内容,因为它们被认为是父组件所持有并传递进来的。使用 :slotted 伪类以明确地将插槽内容作为选择器的目标:

作用:插槽选择器可以用来选择插槽中的内容。

使用示例:

<template>
 <div class="content">
    <slot></slot>
  </div>
</template>
 
<style scoped>
/* 选择默认插槽元素 */
 
.content :slotted(.red) {
  color: red;
}
 
</style>

3、全局选择器 :global()

    如果想让其中一个样式规则应用到全局,比起另外创建一个 <style>,可以使用 :global 伪类来实现 (看下面的代码):

作用:全局选择器可以用来选择不受scoped样式影响的元素。

使用示例:

<template>
  <div class="container">
    <div class="global-child"></div>
  </div>
</template>
 
<style scoped>
  /* 选择全局样式 */
  :global(.global-child) {
    color: red;
  }
</style>

4、混合使用局部与全局样式​

你也可以在同一个组件中同时包含作用域样式和非作用域样式:

<style>
/* 全局样式 */
</style>
 
<style scoped>
/* 局部样式 */
</style>
目录