/deep/样式穿透失效的原因和解决办法
在vue页面,为何有的样式需要限制scoped,为何需要样式穿透,样式穿透的原理是什么,对此进行小结。
问题:vue页面中(样式使用less书写),对iview的组件使用/deep/进行样式穿透修改默认样式,发现在Google Chrome版本64上看样式修改成功,但在火狐浏览器、edge版本101、高版本谷歌浏览器中查看,发现样式穿透失效。
解决:
1.组件内scoped的样式,样式穿透/deep/只写在外层父元素,父元素内部的子元素不再写/deep/
<style scoped>
/deep/ .ivu-form {
...
.ivu-form-item{
...
}
}
</style>
2.全局样式,不写/deep/ 。
问题是解决了,但这是为什么呢?
分析:
1.为什么要加scoped?
为了使当前的样式只作用在当前组件,若无这个限制的话,写在这个组件内的样式就可能会影响其他具有相同css选择器名称组件的样式。
2.为什么加了scoped就能只作用于组件内呢?
Vue.js官网解释道:
<style scoped>
@media (min-width: 250px) { .list-container:hover { background: orange; } }
</style>
这个可选
scoped
attribute 会自动添加一个唯一的 attribute (比如data-v-21e5b78
) 为组件内 CSS 指定作用域,编译的时候.list-container:hover
会被编译成类似.list-container[data-v-21e5b78]:hover
查看页面,发现加了scoped的组件A作用域内的DOM节点和子组件都有了一个自定义属性:data-v-hash,再查看编译后作用于DOM节点的css选择器为 .class-name[data-v-hashA] ,而不同组件的data-v-hash的hash值不一样,所以组件内的样式只作用于本身而不会影响其他相同class(id等)名的组件。 若组件B有相同的class-name,但无scoped,则作用于组件B的css选择器为.class-name,所以组件A的样式.class-name[data-v-hashA] 也不会影响组件B。
如下:
3.为什么使用/deep/后就能样式穿透?
<style scoped>
/deep/ .ivu-form {
...
}
</style>
上面说到:加了scoped的组件作用域内的DOM节点和子组件都有了一个自定义属性:data-v-hash,但子组件只会在最外层会加上父组件的data-v-hash。而加了scoped的情况下,vue编译后的css样式会在我们自定义的选择器后加上[data-v-hash]选择器,但子组件内部的DOM节点并没有父组件的data-v-hash属性,所以样式未生效。
加上/deep/,是使得vue编译此处的css样式时,将[data-v-hash]选择器作为父级条件,作为子组件的DOM,上级肯定会有节点有data-v-hash属性,所以样式作用成功。
例:
F12,查看作用于这个span节点的样式,发现:不加/deep/时,对应的css样式是 .ivu-btn-warning span[data-v-hash] {...},加上/deep/后,对应css变为了 [data-v-hash] .ivu-btn-warning span {...}
4.为什么有的浏览器会样式穿透失败?
<style scoped>
/deep/ .ivu-form {
/deep/.ivu-form-item{
...
}
}
</style>
这种嵌套/deep/的写法,发现在Google Chrome版本64里能样式穿透成功,F12,查看Sources面板,发现页面编译好的样式为:
[data-v-124sd13] .ivu-form .ivu-form-item {....} ......
但在火狐浏览器发现编译后为如下所示,所以ivu-form-item内样式未生效:
[data-v-124sd13] .ivu-form /deep/ .ivu-form-item {....} ......
更多推荐
所有评论(0)