【vue其他相关】理清scoped的表层原理,父子组件样式继承问题,深度选择器解决什么、以及CSS Modules等等

不用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 {}这种形式去精确覆盖具体的值。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值