前言
vue的style中设置scoped属性后,组件实现样式私有化。
但是该组件又使用的其他组件库时(vant,elementui,自定义等),该组件的style中的样式,优先级低,不生效,这个时候需要使用样式穿透(作用得更深)。
一、scoped底层原理
- scoped是通过在DOM以及css中加上
data-v-xxx
唯一标识来实现样式私有化。
1.加上scoped前
<template>
<div class="demo">
样式穿透示例
</div>
</template>
<style >
.demo{
color: rgba(255,0,0,0.5);
}
</style>
2.加上scoped后
<style scoped>
.demo{
color: rgba(255,0,0,0.5);
}
</style>
通过图片可以看到scoped底层是通过在DOM节点
中添加data-v-xxx
,CSS
中通过添加[data-v-xxx]
属性过滤,提高优先级,来实现样式的私有化。
二、为什么需要样式穿透
看一个场景实例:子组件根元素颜色为红色
,非根元素为蓝色
。
父子两个组件style
都使用scoped
属性,在不修改子组件的前提下,在父组件上修改子组件的颜色为绿色
。
// 子组件
<template>
<div class="c1">
子组件根元素(red)
<div class="c2">
子组件非根元素(blue)
</div>
</div>
</template>
<style scoped>
.c1{
border: 1px dashed #000;
margin-top: 10px;
padding: 5px;
color: red;
}
.c1 .c2{
border: 1px dotted #000;
color:blue;
}
</style>
// 父组件
<template>
<div class="demo">
父组件
<css-demo class="son"></css-demo>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import cssDemo from "./css-demo2.vue"
export default Vue.extend({
components:{ cssDemo }
})
</script>
<style scoped>
.demo{
width: 200px;
padding: 10px;
border: 1px solid rgba(0,0,0,1);
color: #000;
}
.son{
color: green;
}
.son .c2{
color: green !important;
}
.c1 .c2{
color: green !important;
}
.son.c1 .c2{
color: green !important;
}
</style>
- 可以看到只有子组件的根元素作用有生效,但是子组件的非根元素样式并没有生效,即使使用了
!important
。 - scoped在渲染的时候,如果组件内部还有子组件,只会在子组件的根元素加上
data-v-xxx
属性。
当加上样式穿透后
// 父组件
<style scoped>
>>> .c1 .c2{
color: green !important;
}
</style>
三、样式穿透的方法
vue
中针对不同的样式类型(css
,less
,scss
)有不用的样式穿透方法。
css
使用>>>
less
使用/deep/
scss
使用::v-deep
1. css
<style scoped>
>>> .c1 .c2{
color: green !important;
}
</style>
2. less
<style scoped lang="less">
/deep/ .c1 .c2{
color: green !important;
}
</style>
3. scss
<style scoped lang=”scss“>
::v-deep .c1 .c2{
color: green !important;
}
</style>