Vue样式隔离scope
Vue组件之间没有做到样式隔离,Vue中的样式隔离,是通过scoped
属性来实现的。当在<style>
标签上使用scoped
属性时.基本原理概括为以下几个步骤:
-
为当前组件模板的所有DOM节点添加相同的attribute,添加的属性与其他的scope不重复,data属性(形如:data-v-123)来表示他的唯一性。
-
在每句css选择器的末尾(编译后的生成的css语句)加一个当前组件的data属性选择器(如.ipt input[data-v-123])来私有化样式
-
如果组件内部包含有其他组件,只会给其他组件的最外层标签加上当前组件的data属性
-
样式隔离的效果:只能选中本组件元素,无法选中子组件的元素。
为什么需要样式穿透
在Vue项目中,当我们引入第三方组件库时(如使用element-ui),需要在局部组件中修改第三方组件库样式,而又不想去除scoped属性造成组件之间的样式覆盖。这时候我们就需要样式穿透
来实现我们想要的效果。
原理
让父组件在有scoped的标签里,可以访问到子元素选择器,从而使用子元素的选择器修改子元素的样式。
具体原因
因为vue在做样式隔离时,有子组件时只会在最外层的元素添加data属性,而css添加时,只会在最后添加属性选择器。而:deep
样式穿透就是要解决,css选择器添加问题。
例如:比如修改a-input的背景颜色:
<template>
<div>
<el-input class="ipt"></el-input>
</div>
</template>
<style scoped lang="scss">
.ipt{
input{
background-color: red;
}
}
</style>
dom:
给最外层元素添加data属性,即:
css:
在最后添加样式选择器:
不生效的原因是因为dom中选择器为ipt[data-v-b8cedf19] input
而style中默认为.ipt input[data-v-b8cedf19]
,所以导致样式不生效。
解决方法
添加deep: less中添加deep的方式:
<style lang="less" scoped>
外层 /deep/ 第三方组件 {
\样式\
}
</style>
例:
<template>
<div class="parent">
<child-component></child-component>
</div>
</template>
<style lang="less" scoped>
.parent /deep/ .child {
// Your styles here that affect .child component
color: red;
}
</style>
在这个示例中,.parent
是有作用域的,而 /deep/
则表示穿透作用域,影响到 .child
组件的样式。这确保了你可以在父组件的样式中修改子组件的样式。
记住,/deep/
或 ::v-deep
是 Vue 2.x 提供的穿透作用域的方式。在 Vue 3.x 中,可以使用 ::deep
或 ::slotted
来实现类似的效果。