Vue样式穿透
vue文件的style标签的scoped属性作用:PostCSS在元素标签上添加特殊属性值,在样式的选择器后面添加属性选择器,实现了组件样式的私有化,防止组件之间的样式污染(比如相同类名的元素)。
但在使用scoped属性时,会遇到样式问题。需要使用样式穿透解决
scoped原理
ParentComponent.vue文件
<template>
<div>
<p class="parent">父组件</p>
<ChildComponent></ChildComponent>
</div>
</template>
<script>
import ChildComponent from "./ChildComponent.vue";
export default {
components: {
ChildComponent,
},
};
</script>
<style scoped lang="less">
.parent{
color: red;
font-size: 20px;
}
</style>
在父组件的style标签中启用了scoped属性后,可以看到父组件的所有元素都添加了相同的特殊属性,同时在子组件的根元素上也有(只有子组件的根元素才有,其他没有,这里注意到子组件的p标签并没有)。
.parent选择器也变成了.parent[data-v-xxx],也就是添加了属性选择器。
遇到问题
使用第三方组件库的组件时,时常需要调整子组件内部的样式。加上scoped属性后,发现无法使子组件内部标签选择器的样式生效。
举例:
现在我想通过.child p选择器,选择子组件中的p元素,调整样式,这时是没有效果的
ParentComponent.vue文件
<template>
<div>
<p>父组件</p>
<ChildComponent class="child"></ChildComponent>
</div>
</template>
<script>
import ChildComponent from "./ChildComponent.vue";
export default {
components: {
ChildComponent,
},
};
</script>
<style scoped lang="less">
.child p {
color: red;
font-size: 20px;
}
</style>
可以看到,这时的选择器变成了.child p[data-v-xxx],属性选择器加到了p后面,但是在图一我们看到子组件的p标签是没有特殊属性的,所以这时样式没有生效。
通过样式穿透,可以解决这个问题。
解决方案:样式穿透
vue中针对不同的样式类型(css,less,scss)有不用的样式穿透方法。
- css 使用 >>>
- less 使用 /deep/
- scss 使用 ::v-deep
ParentComponent.vue文件
<style scoped lang="less">
.child /deep/ p {
color: red;
font-size: 20px;
}
</style>
可以看到,/deep/放在谁的后面,属性选择器就加在哪个选择器的后面。图中显示这时属性选择器在.child选择器后面,选择器这时筛选过滤出来的是“具有.child类名和具有[data-v-xxx]属性的元素的所有子元素中的p元素”,效果符合预期。