文章目录
不用scoped带来的样式混乱
如果在vue文件中的style的标签里,不加scoped标识,很容易造成css污染,且无法理清生效的顺序。
例如
A组件:
<div class="box">
啊啊啊啊啊啊
</div>
<style>
.box {
color: red;
}
</style>
此时如果有其他兄弟组件也写了这个样式,例如B组件:
<style>
.box {
color: blue;
}
</style>
那么有可能生效的box样式就是蓝色。
如果没有B组件,AB的共同父组件也写了个样式:
<style>
.box {
color: yellow;
}
</style>
那么生效的必然是父组件覆盖后的黄色。
但是!当B组件也在的时候,生效的却是蓝色。
就理不清规律,在项目复杂的时候就会难以维护和调试。
我猜测是编译后的顺序覆盖问题
加入scoped隔离
当我们给A组件开启scoped的时候,去审查元素:
<style scoped>
.box {
color: red;
}
</style>
会发现多添加了一个属性,v-后面的是一个哈希唯一值。然后我们的box类名的样式,会自动改成属性选择器:
这时候,B组件的样式就不会影响到A组件了,父组件的样式也不会影响到A组件了。
scoped是会继承的
当A组件和父组件同时开启scoped,A组件的根元素会默认继承父组件的哈希值:
所以父组件的样式也会对A组件生效,并且覆盖了子组件:
因为在vue的渲染过程中,理论上是子组件先挂载完毕后,父组件才开始挂载,所以后者的样式把前者覆盖了。
去官网看解释:
如何避免继承带来的副作用
我个人平时的开发习惯还是会在子组件的类名前面加上前缀,例如父组件叫userCenter.vue,子组件的类名就取userCenter-box,以此类推。
可这样scoped的意义不就只在兄弟组件间才能发挥作用了吗?CSS Modules就解决了这个问题,下面有记录。
还有一种方法,因为scoped的继承是继承在子组件的根节点上的,所以只需要给子组件套一层没有意义的div即可:
<template>
<div>
<div class="box">
啊啊啊啊
</div>
</div>
</template>
解决副作用后又想影响子组件某个样式(深度选择器)
在一些特殊需求下,我们不想改子组件的样式代码,同时在继承问题已经处理了的情况下,还想通过父组件影响子组件中的某个样式怎么办,官方也给我们了好方案:
我们先给A组件根节点加上一个类名
<template>
<div class="box-wrap">
<div class="box">
啊啊啊啊
</div>
</div>
</template>
然后在父组件加入一个深度选择器
<style scoped>
.box-wrap >>> .box {
color: yellow;
}
</style>
搞定,文字变成黄色。
如果工程用了sass预处理器,>>>是无法解析的,用下面的试试,并且一定要给style标签加上scoped属性,这样深度选择器才能被postCSS 解析。
/deep/
::v-deep
关于哈希值背后是怎么生成的可以看:【vue其他相关】简单的来捋清楚vue-loader做了啥事
CSS Modules方案
<style module>
.red {
color: red;
}
.bold {
font-weight: bold;
}
</style>
这样,直接能够让你的类名变成唯一的,也就是整个工程独一份的,这样无论是父子关系,兄弟关系,乱七八糟关系都不会影响到。
具体配置和使用方式看官方地址吧
优点:
- 完美的样式隔离
- 可以通过js去获取到样式
缺点:
- 写法稍微麻烦点
改第三方ui库样式的一些小心得
改三方组件的样式时候,经常遇到这样的情况
<template>
<div class="home">
<el-xxx></el-xxx>
</div>
</template>
<style scoped>
.home .el-xxx-item{}
</style>
当我们改el-xxx这组件里面的某个标签样式时不生效
首先不要用important
,应该是组件中有更高的权值样式,可以控制台看看。
有可能是第三方组件里有个.el-xxx .el-xxx-item {}
这样的选择器在生效中。所以可以.home .el-xxx .el-xxx-item {}
这种形式去精确覆盖具体的值。