: deep 针对Dialog/Message-box类组件不生效

1,925 阅读1分钟

前言

在日常开发当中,我们通常会在<style>标签上加上scpoed属性来进行样式隔离,避免因为命名重复造成的样式污染;

但是也正是因为如此,一旦使用了scoped属性,我们就无法对文件当中的子组件进行样式控制

由此Vue-loader提供了深度选择器——deep,在Vue3+scss当中的写法为:deep(类名){}

项目开发中,经常根据需求对element-ui当中的组件进行一些样式的修改,这时候会使用到:deep

失效原因

在面对<el-card/>或者是<el-input/>等组件时,scoped+:deep的组合可以非常完美地发挥样式自定义的效果,且对项目当中同类组件不产生污染

但是面对dialogmessage-box这些弹窗型组件时,会发现完美组合失效了

这是为什么呢???

message-box为例,在这个小弹窗没有出现之间,页面的元素结构如下

Snipaste_2022-07-15_16-06-36.png

当小弹窗出现时,页面元素如下:

image-20220715160816150.png

可以看出,是在和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标签,这样会将全局代码分散在各个子文件当中,最好是放在全局文件中统一进行管理;

以上 问题完美解决!!!