什么是样式穿透
当我们在vue项目中引用到第三方组件时,比如element-ui,常常需要更改某些元素的样式,但如果使用常规的css样式覆盖的方式是经常无效的,那么我们就要用到“样式穿透”的方法。
scoped生效原理
在一个组件中,我们定义组件样式一般写在页面的最下方,以style包裹
<style>
.div{
}
</style>
为了不污染全局样式,我们在style上加一个scoped修饰符,这个样式就只在当前组件的范围内有效
<style scoped>
.div{
}
</style>
但这是如何做到在当前组件范围内有效的呢?我们打开F12,查看一下元素的DOM结构就可以看出:
在每个dom元素上,有一个data-v-xxxxxxxx的标识符,这个标识符就是保证scoped有效的根本!我们定位到button上,查看css样式:
我们看到元素后面被加上了[data-v-xxxxxxxx]属性,这也就是CSS的属性选择器,只有拥有这个属性的元素或类才会应用此样式。每个组件下[data-v-xxxxxxxx]这个id值是一致的,所以限制了其作用范围。
这个方法是基于PostCss的,关于PostCss可以看其官网的介绍,这里就不多讲了。PostCss官网
清楚了这个原理之后,我们就可以解释为什么很多第三方组件引入进来,通过常规的css样式覆盖是无效的,因为该组件是scoped,父组件是触及不到其内部的样式的!
那我们要是必须要改变第三方组件的样式要怎么办呢?这里就要说样式穿透的方法了。
所谓样式穿透,就是在父级组件中强制去修改子级组件的内部样式,注意这里的父子层次并不一定是一级,可能是很多级。
按不同的css的渲染器写法也是不同的
样式穿透写法
CSS写法
在要修改的样式前添加>>>符号,实际上>>> ::v-deep /deep/三者都可用
.wrapper >>> .el-card__header{
border:none;
}
SCSS语法
在要修改的样式前添加 ::v-deep ,实际上/deep/也可用,但是在vue3中可能会报错
::v-deep .el-card__header{
border:none;
}
sass语法/less语法
在要修改的样式前添加::v-deep ,/deep/也是可用的
.wrap /deep/ .el-card__header{
border:none;
}
- 如果你使用的是
css,没有使用css预处理器,则可以使用>>>,/deep/,::v-deep。 - 如果你使用的是
less或者node-sass,那么可以使用/deep/,::v-deep都可以生效。 - 如果你使用的是
dart-sass,那么就不能使用/deep/,而是使用::v-deep才会生效。 - 但是如果你是使用
vue2.7以上版本以及包括vue3,::v-deep也会生效,但是会有警告⚠️
警告说的很清楚,
::v-deep已经废弃,应该使用:deep()
总的来说,::v-deep适应性更好,更多地使用。
为啥要有这三种不同的写法??因为不同的编译解析器识别的语法不同,写错会报错。