最近在写一个vue+element-ui项目,使用element-ui某些组件修改样式时,老是需要加上/deep/深度选择器,以前只是知道这样用,但是还不清楚他的原理,这次就来好好的梳理一下
1. 首先我们需要知道css中的属性选择器
w3c解释:对带有指定属性的 HTML 元素设置样式。
可以为拥有指定属性的 HTML 元素设置样式,而不仅限于 class 和 id 属性。
注释:只有在规定了 !DOCTYPE 时,IE7 和 IE8 才支持属性选择器。在 IE6 及更低的版本中,不支持属性选择。
下面的例子为带有 title 属性的所有元素设置样式:
[title]{
color:red;
}
2. vue中<style>加上scoped会有什么变化
先写一段css
<style lang="scss">
.login {
background: url('~@/assets/images/bg.png') no-repeat;
background-size: cover;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
.login-form {
max-width: 380px;
}
}
</style>
没有加scoped
,看一下浏览器渲染结果
加上了scoped
,再看一下有什么变化
发现多了一个data-v-hash
属性,也就是说加了scoped,PostCSS给一个组件中的所有dom添加了一个独一无二的动态属性,然后,给CSS选择器额外添加一个对应的属性选择器来选择该组件中dom,这种做法使得样式只作用于含有该属性的dom——组件内部dom,可以使得组件之间的样式不互相污染。
3. 为什么加上scoped时,修改第三方组件需要加上 /deep/
我在实际中遇到的例子:我使用了element-ui的el-card组件,想要修改它的头部样式,于是在调式工具中查看了他的类名
发现是el-card__header,然后对样式修改,发现并没有效果
.el-card__header {
padding: 13px 20px;
}
因为渲染出来的选择器是
.el-card__header[data-v-hash]
,而子组件dom上没有这个[data-v-hash]
这个属性,所以选择不到这个dom,可在Sources下找到以下代码
于是加了/deep/,嗯,这次起效果了,但是为什么这样就能起效果
/deep/ .el-card__header {
padding: 13px 20px;
}
查看了下样式表,发现多了个当前组件的[data-v-hash]
属性选择器
再看一下编译完的文件
由上得出/deep/
原理是在样式表上加了父组件的[data-v-hash]
这个属性选择器,达到控制子组件样式的效果
结论
- 加上scoped会在当前组件的dom加上
[data-v-hash]
属性,在css中加上[data-v-hash]
属性选择器,达到组件之间的样式不互相污染的效果。 - 使用
/deep/
深度选择器会在css中加上[data-v-hash]
这个父代选择器来控制子组件样式,如[data-v-hash] .el-card__header
。