插槽slot涉及到的样式污染问题

2024-01-07 18:33:37

1. 前言

本次我们主要结合一些案例研究一下vue的插槽中样式污染问题。在这篇文章中,我们主要关注以下两点:

  • 父组件的样式是否会影响子组件的样式?
  • 子组件的样式是否会影响父组件定义的插槽部分的样式?

2. 准备代码

2.1 父组件代码

<template>
  <div class="wrap">
    <div>
        parent-root
    </div>
    <A>
        <div slot-parent>
            <div class="container">parent_content</div>
        </div>
    </A>
  </div>
</template>
<script lang=ts setup>
import A from './A.vue';
</script>
<style lang=scss scoped>
.wrap{
    width: 400px;
    height: 400px;
    background-color: lightgreen;
    color: red;
}
.container{
    background-color: lightcoral;
}
</style>

2.2 子组件代码

<template>
  <div class="wrap" child>
    <div>
        child-header
    </div>
    <slot></slot>
    <div class="container">
        child-footer
    </div>
  </div>
</template>
<script lang=ts setup>
</script>
<style lang=scss scoped>
.container{
    width: 100px;
    height: 100px;
    background-color: lightblue;
}
.wrap{
    border: 1px solid black;
}
</style>

2.3 最终编译的代码

在这里插入图片描述
通过上面的代码,我们得出几个结论:

  • 子组件的顶级标签会继承父组件的文件指纹。
  • 子组件的插槽(父级定义的插槽代码)的顶级标签不会继承子组件的文件指纹。

3. 问题分析

3.1 父组件是否污染子组件问题

通过上面的分析,我们知道父组件的文件指纹会继承到子组件的顶级标签上,也就是说父组件的样式有可能会影响子组件的样式。
比如,我们在父组件中定义了wrap的样式:

.wrap{
    width: 400px;
    height: 400px;
    background-color: lightgreen;
    color: red;
}

那么他生成的代码如下:
在这里插入图片描述
在这里插入图片描述
此时,我们发现在父组件定义的wrap样式在子组件的顶级标签仍然起作用。此时,就会污染子组件。

目前我还没有比较好的解决方案,只能在实际开发中对于类名的命名尽量避免相同。

3.2 子组件是否会污染插槽中的样式

通过上面的分析,我们知道插槽中的html片段并不会携带子组件的文件指纹。由于在子组件定义的样式都会携带子组件的文件指纹,所以子组件定义的样式并不会影响插槽中html片段的样式。
当然,这个假定也都是在不使用v-deep的前提下生效。如果掺杂v-deep呢?

3.3 v-deep下子组件插槽样式的污染情况

父组件代码

<template>
  <div class="wrap">
    <div>
        parent-root
    </div>
    <A>
        <div slot-parent>
            <div class="container">parent_content</div>
        </div>
    </A>
  </div>
</template>
<script lang=ts setup>
import A from './A.vue';
</script>
<style lang=scss scoped>
.wrap{
    width: 400px;
    height: 400px;
    background-color: lightgreen;
    color: red;
}
.container{
    background-color: lightcoral;
}
</style>

子组件代码

<template>
  <div class="wrap" child>
    <div>
        child-header
    </div>
    <slot></slot>
    <div class="container">
        child-footer
    </div>
  </div>
</template>
<script lang=ts setup>
</script>
<style lang=scss scoped>
.container{
    width: 100px;
    height: 100px;
    background-color: lightblue;
}
.wrap{
    border: 1px solid black;
    ::v-deep .container{
        border: 5px dashed lightsalmon;
    }
}
</style>

在这里插入图片描述
通过上面分析的代码,我们发现parent_content所在的标签和child-footer所在的标签都生效了,也就是说子组件的样式污染了父组件的标签。
这一点在开发中要注意,要慎重使用v-deep,不然会产生难以预料的结果。这里有可能有人会想,在最后加一个v-deep就行了呗。
而实际事与愿违,因为对于多个v-deep,vue只能识别出第一个,后面的会按照样式名为v-deep进行渲染。

.wrap{
    border: 1px solid black;
    ::v-deep .container::v-deep{
        border: 5px dashed lightsalmon;
    }
}

在这里插入图片描述

文章来源:https://blog.csdn.net/oYinHeZhiGuang/article/details/135433585
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。