Vue 深度作用选择器 /deep/穿透 与scoped

下面是引用的组件:
在这里插入图片描述
要求: 修改 “黑马头条” 字体颜色.

<style lang="less" scoped>
 .van-nav-bar__title {
	color: #ffffff;
	}
</style>

↑,无法改变颜色.
因为,我们在加了 scoped 之后,编译后生成的样式文件 会自动添加一个hash值,如下:
(*同样,html的代码,也会自动添加hash属性)

.van-nav-bar__title[data-v-7ba5bd90] {
	color: #ffffff;
}

这样就无法修改组件里面的样式了.
解决方法就是: 添加/deep/

/deep/ .van-nav-bar__title {
	color: #ffffff;
}

这样编译后生成的css文件是:

.van-nav-bar__title {
    color: #ffffff;
}

↑ 这样,此样式就不会因为有scoped 自动带上hash值

其他例子:

使用 scoped 后,父组件的样式将不会渗透到子组件中。

<template>
  <div id="app">
    <el-input  class="text-box" v-model="text"></el-input>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      text: 'hello'
    };
  }
};
</script>

<style lang="less" scoped>
.text-box {
   input {
    width: 166px;
    text-align: center;
  }
}
</style>

解决方法:
使用深度作用选择器 /deep/

<template>
  <div id="app">
    <el-input v-model="text" class="text-box"></el-input>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      text: 'hello'
    };
  }
};
</script>

<style lang="less" scoped>
.text-box {
  /deep/ input {
/*
    ↑等同于[data-v-7ba5bd90] input {}
    其中:[data-v-7ba5bd90] 是父组件的input属性,deep就是获取这属性值
*/
    width: 166px;
    text-align: center;
  }
}
</style>

转载更详细:
一,原因
我们在使用element ui或者自定义通用组件的时候,有时候需要在父组件中修改子组件的样式,就容易遇到这么一个情况,在父组件中修改子组件的样式无法生效?
原因是我们在vue页面的样式通常会加scoped,来保证这个vue组件的样式仅仅作用于这个组件,而不会影响到其他组件,这个scoped的原理,这篇博客讲得很清晰明了了。
https://blog.csdn.net/qq_41800366/article/details/107062781
也就是:

vue 给该组件的每一个标签自动添加一个唯一的 attribute, 这里
注意,你会发现vue给子组件的根标签也打上了这一个唯一的attribute, 但是子组件的其他标签却没有打上。
编译后会发现,添加的css样式变成了如下:添加了唯一的标签,这也就是vue scoped 实现样式隔离的原理

在这里插入图片描述

二,官方的解决办法
那如何在父组件中更改子组件的样式呢?
官方提供的方法是样式穿透,他的原理就是在父组件中,给对应层级下的html结构都加上该组件的这个唯一的 attribute,从而覆盖子组件的原有样式。
至于样式穿透的写法,网上都有,>>>也好,::v-deep也好,/deep/也好,都是很容易查到的,就不再多说。
例如假定这个p标签是子组件中的。

<style scoped>
/deep/p{
  color: deepskyblue;
}
</style>

在父组件中这样写,就可以覆盖它的样式了!
编译出来是这样的:

[data-v-7ba5bd90] p {
    color: deepskyblue;
}

三,另一种解决办法
我们加scoped是为了保证此组件的样式不影响到全局,从而限定住,那么,我们只要在全局定义样式,就可以修改任何组件中的对应样式了,因此,平时我们所说的在全局修改element ui的样式,之所以能生效,就是这个原因。
当然,我们现在是想在父组件中修改子组件的样式,那么就可以在父组件中再写一个style块,不给scoped,那么这个样式就是全局的了,和全局定义没有差别,只是它写在组件中的样式中罢了。
在这里插入图片描述

比如说上图,1中是仅仅在本页面中起作用的样式,而2中则是全局起作用的,任何组件都会起作用(只要没有被覆盖样式)

四,最优的解决办法
第三种办法,会有一个缺点,不加scoped的样式,它是全局的,会污染到其他页面,比如另一个页面也用到了这个el-dialog组件,他的样式背景色也会变成红色。
而我们既然把这个样式写在这个组件文件中,那肯定是希望它仅仅在此组件中(包含该组件的页面子组件)中生效,而不会污染全局的其他样式。
这就需要理解一个概念,我们常常说dom结构是树结构,其实css也是结构,它和对应的html结构相互依存,类似一个映射的关系。
在这里,只要在我们想要的地方的祖先元素上加一个自定义类名,然后再写全局的样式,那么这个样式就会被我们限定在仅仅这个类名下的对应结构才会生效,也就是,它虽然是全局样式,但是生效范围可以人为控制了!
比如说这里:
在这里插入图片描述

也就是,这时候,它是全局样式,但是仅仅在类名为fileImport的dom树分支下的dialog才生效,其他页面不会生效,因为其他页面没有类名为fileImport的dom结构!于是它既是私有的,又是全局的,还是可定制的!其他页面想要使用,祖先元素加上一个名为fileImport的类即可!
我真tm机智!!!

五,个人遇到的案例
在这里插入图片描述

全局的dialog样式我配置好了,因为其他页面这里都是有标题的,所以设置了为元素来提供一个logo那样的小图标,但是这个对话框居然没有标题,所以,需要撤除这里的before,一开始,我是在scoped的样式中直接把before的content设置为none,但是无论怎么样都不生效,然后考虑到它其实是属于该页面的子组件,应该加个样式穿透,但是依旧不生效,这里我没有搞懂,虽然全局定义了,但是按道理,只要我用了样式穿透,让该子组件也有对应的scoped属性,再设置样式,只要满足css权重大于全局设置的样式,就可以覆盖样式才对,(或者权重一样,但是后写的样式就可以覆盖前写的),没道理不生效的。
最后的解决办法是使用方案四解决的,两个style,刚开始没考虑权重依旧没生效,然后注意到全局的样式是三个类加一个伪类,权重40,我这里写至少也得权重40才能生效。(因为全局的public.css是在main.css文件中的,最先生效,而页面的css在他之后渲染,故而权重相同,页面的会覆盖全局的)。
于是写成这个样子:
在这里插入图片描述

最后生效:
在这里插入图片描述

六,第五个案例的进展
至于五中为啥样式穿透不生效,我也很奇怪,没找到原因,是因为我样式穿透没写对?????
我看了下dom结构,确实没有生效:
在这里插入图片描述

第一层data-v-48cac322是一个scoped
第二层是data-v-751c36f6,其中分界点是class为fileImport的元素节点。它是两组件的结合节点,同时具备两个组件的scoped分配的data属性。
第三层是dialog组件,它是element的组件,让我感到奇怪的是,从这里看,这个dialog组件并没有使用vue的scoped写法????
所以没有scoped分配的data属性,否则el-dialog__wrapper这个节点作为两组件的结合处,应该也是具备两个属性的!!!
而我之所以说我样式穿透没有生效,是因为,一旦样式穿透生效的话,就会把data-v-751c36f6传递到dialog组件中去,其对应的html节点也应该具备这个data属性!!!
懵了,我没有哭~~,太晚了,我要去睡觉觉了。
————————————————
版权声明:本文为CSDN博主「笑道三千」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42349568/article/details/113448884

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值