在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>