Vue为何打包后的样式不一致?

有两个组件<Layout><HelloWorld>,代码如下:

<!-- layout -->
<template>
    <div>
        <div class="header">
            <slot></slot>
        </div>
    </div>
</template>

<script>
export default {
    name: 'Layout',
}
</script>

<style lang="scss" scoped>
.header {
    background: linear-gradient(135deg, #7f7fd5, #86a8e7, #91eae4);
    height: 100px;
    display: flex;
    align-items: center;
}
</style>
<!-- helloworld -->
<template>
    <Layout>
        <div class="header">Installed CLI Plugins</div>
    </Layout>
</template>

<script>
import Layout from './Layout.vue'

export default {
    name: 'HelloWorld',
    components: { Layout },
}
</script>
<style lang="scss" scoped>
.header {
    background: rgb(38, 57, 224);
    height: 200px;
}
</style>

此时打包后样式应用如下:
image.png
第一个header使用第一组样式,第二个header在继承的基础上覆盖了部分样式

但将layout最外一层div标签去掉后:

<div>
    <div class="header">
        <slot></slot>
    </div>
</div>

变成

<div class="header">
    <slot></slot>
</div>

再次打包,得到的结果是
image.png
两个header应用相同的样式

请问为什么多了一层div标签会造成打包结果不同?

阅读 1.2k
avatarAI BotBETA

根据您提供的代码和描述,问题似乎与Vue组件的样式作用域和继承规则有关。

在Vue中,每个组件的样式默认是scoped的,即样式只应用于当前组件,不会影响到其他组件。这是由于Vue使用了PostCSS插件来将每个组件的样式作用域限制在其自身的范围内。

然而,在某些情况下,样式可能会跨越组件的边界继承或冲突。这通常是由于CSS的选择器优先级和继承规则导致的。

在第一个例子中,Layout组件的样式中定义了.header选择器,并且该选择器的样式被应用到了Layout组件的<div class="header">元素上。由于该选择器的作用域被限制在Layout组件内,因此它不会影响到HelloWorld组件中的<div class="header">元素。

然而,在第二个例子中,当您去掉了Layout组件的最外层<div>标签后,<div class="header">元素成为了根元素,这意味着它的样式将影响到所有子元素。因此,在打包后的结果中,两个header元素都应用了相同的样式。

这表明在第一个例子中,由于Layout组件中的.header选择器被限制在其内部的作用域中,因此不会影响到其他组件的元素。而在第二个例子中,由于根元素的样式会继承到所有子元素上,因此两个header元素都应用了相同的样式。

总结起来,多了一层div标签会造成打包结果不同,因为这影响了样式的范围和继承规则。当一个元素被包裹在一个具有样式的父元素内时,它的样式会继承自父元素;而当一个元素成为根元素时,它的样式将影响到所有子元素。

1 个回答

和 CSS 作用域有关系,可以看到你 slot 进来的 .header 元素,同时拥有了当前层级和layoutscope 属性。自然可以应用到两个组件各自的CSS样式。

图片.png

如果需要避免这个问题,BEM的命名方式还是需要的。其实很多开发者在最后并不会默认开启组件样式的 scope 属性。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题