Scoped CSS规范是Web组件产生不污染其他组件,也不被其他组件污染的CSS规范。这样在打包的时候会生成一个独一无二hash值,这样父组件的样式就不会影响到子组件了
但我们在使用第三方组件库、公共组件的时候,有时需要对这些组件进行一些样式修改,由于scoped的限制,会使得我们直接修改组件样式不生效。这个时候可以使用深度选择器–/deep/ 覆盖子组件样式
💡:深度选择器: /deep/ 和 “<<<" 二者作用是一样的,只是一些css预处理器,例如sass不能解析>>>属性
,这种情况下可以用deep,它是>>>的别名,工作原理相同
/deep/原理?
在编译组件的时候,如果当前组件内style标签上有scoped属性时,就会给当前组件所有标签上添加一个【data-v-hash】属性,且在标签的css选择器的结尾加上和属性同样的字段,起到唯一性的作用,实现类似于"作用域"的作用,那么就使得当前组件内的样式只会作用于当前组件内的元素
/*父组件结构*/
/*父组件里使用child子组件*/
<template>
<div class="father-div">
<span class="father-text">我是父组件</span>
<child />
</div>
</template>
<style lang="scss" scoped>
.father-div{
.father-text{
color:red;
}
}
</style>
/*子组件结构*/
<template>
<div class="child-div">
<span class="child-text">我是子组件</span>
</div>
</template>
<style lang="scss" scoped>
.child-div{
.child-text{
color:pink;
}
}
</style>
由于组件的style标签上有scoped属性,所以浏览器解析时会给所有标签添加一个【data-v-hash】,且在class选择器的结尾加上和属性同样的字段,所以在浏览器上看到父组件的dom结构就是这样的👇
<div data-v-7fa1cbbc class="father-div" >
<span data-v-7fa1cbbc class="father-text">我是父组件</span>
</div>
对应的css样式也会在其选择器后面加上属性相同的字段👇
.father-div[data-v-7fa1cbbc] {
width: 200px;
height: 20px;
}
.father-div .father-text[data-v-7fa1cbbc] {
color: red;
}
如果当父组件和子组件的样式都是用了scoped属性时,子组件最外层的标签既会被加上当前组件的hash值,又会加上父级组件的hash值。
所以子组件在浏览器上解析的结构是这样的👇
<div data-v-384b136e data-v-7fa1cbbc class="child-div" >
<span data-v-384b136e class="child-text">我是子组件</span>
</div>
现在要是想在父组件内直接改变子组件内类名为child-text的span标签的样式时,就会发现不好使
/* 父组件的css样式 */
<style lang="scss" scoped>
.father-div{
.father-text{
color:red;
}
.child-div { //直接修改
.child-text{
color: blue;
}
}
}
</style>
因为子组件的style标签也加上有scoped属性,子组件元素本身有自己的样式,浏览器会解析组件本身的样式,渲染对应的dom
.child .child-text[data-v-384b136e] { //类选择器的hash值只与子组件标签的hash值对应
color:pink
}
⚠️⚠️⚠️ 直接修改时不好使的原因,是因为写在父组件内的样式解析的是父组件的hash值,但浏览器上解析的子组件内的标签添加的是子组件的hash值,对应的则是子组件内的样式,与父组件内的hash值对应不上,所以父组件内的样式覆盖也没有生效
所以,这个时候就可以使用深度选择器/deep/
来解决👇
/* 父组件的css样式 */
<style lang="scss" scoped>
.father-div{
.father-text{
color:red;
}
/deep/ .child-div { //使用深度选择器修改
.child-text{
color: blue;
}
}
}
</style>
因为浏览器解析时,遇到"/deep/“的时候会将”/deep/"的位置替换成组件的hash值👇
.father-div[data-v-7fa1cbbc] .child-div .child-text{
color: blue;
}
这样只需要注意css的权重就可以覆盖子组件内的样式了,页面上就会展示我们想要的样式了
如果只是想要修改子组件最外层结构都样式,不需要/deep/就可以在父组件内覆盖样式,因为子组件内最外层的标签带了父、子组件的两个hash值,所以在父组件和子组件内都可直接定义其样式