前言
在日常开发当中,我们通常会在<style>标签上加上scpoed属性来进行样式隔离,避免因为命名重复造成的样式污染;
但是也正是因为如此,一旦使用了scoped属性,我们就无法对文件当中的子组件进行样式控制
由此Vue-loader提供了深度选择器——deep,在Vue3+scss当中的写法为:deep(类名){}
项目开发中,经常根据需求对element-ui当中的组件进行一些样式的修改,这时候会使用到:deep
失效原因
在面对<el-card/>或者是<el-input/>等组件时,scoped+:deep的组合可以非常完美地发挥样式自定义的效果,且对项目当中同类组件不产生污染
但是面对dialog、message-box这些弹窗型组件时,会发现完美组合失效了
这是为什么呢???
以message-box为例,在这个小弹窗没有出现之间,页面的元素结构如下
当小弹窗出现时,页面元素如下:
可以看出,是在和app同级层里加了div,因此不受随机属性data-v-app控制,而我们知道:deep发挥作用的原理是通过遍历到该Vue节点元素,在该节点上添加一个随机的data-v-xxxxxxx的属性,将类名和随机属性结合来发挥作用;
但像上文出现的这种情况,这个MessageBox就不再属于Vue节点元素,无法进行随机属性的分配,那么:deep会出现失效
类似的像Dialog这种,只要没有出现app节点内的元素,:deep都将失效;
解决方式
方案一:
去掉style标签的scoped属性;
这种方式简单暴力,但弊端也显而易见,影响的是全局样式,命名不规范会造成样式污染;(不建议使用)
方案二:
利用组件自身的样式属性;
当不要进行大量样式修改时,可以使用组件自身提供的样式属性,一般会要求属性值为CSSProperties;
例如Message-box组件的custom-style属性
这种方式也存在一定的缺点,就是也不是所有的组件会都暴露出修改样式的属性,所以并不能满足所有的需求;
方案三:
自定义类名+全局样式——完美方案
首先我们可以通过组件暴露的自定义类型属性为组件添加类名,例如Message-box组件的custom-class属性;
再在全局样式表中,通过类名结合的方式进行样式改变
代码如下:
<script>
const openMessageBox = () => {
MessageBox({
title: 'Title',
message: 'Textxxxxxxxxxxxxxxx',
customClass: 'stand_message_box'
type: 'warning'
}).then(() => {
window.open('http://10.101.53.4/auth/#/user')
})
}
</script>
<style scoped>
:deep(.message-box_header){ //无效
font-size: 600
}
</style>
//再写一个style标签,或放在全局style文件当中
<style>
.stand_message_box .message-box_header{ //有效
font-size: 600
}
</style>
这种方式就既可以控制你需要改变的组件样式,不必全局修改,又能完美解决不生效的情况;
注:不推荐写两个style标签,这样会将全局代码分散在各个子文件当中,最好是放在全局文件中统一进行管理;
以上 问题完美解决!!!