vue 3 中范围样式和深度样式的问题

Dan*_*ega 6 vue.js vue-component vuejs3 vue3-sfc-loader

我在尝试在 vue3 中为父母的孩子设置样式时遇到很多问题。

在本例中,我创建了一个带有一些 css 属性的通用按钮,并尝试从其他组件自定义此按钮

家长

<template>
  <OwnButton
    class="accept-button"
    @ownButtonClicked="emit('accept')"
  >
    <slot> 
      ACCEPT
    </slot>
  </OwnButton>
</template>

<script setup>
import OwnButton from 'path/to/own-button.vue';

const emit = defineEmits(['accept']);
</script>

<style scoped>
.accept-button :deep(.own-button)
{
  background-color  : #4CAF50 !important;
  outline-color     : green !important;
}
.accept-button :deep(.own-button:hover)
{
  background-color: green !important;
}
</style>
Run Code Online (Sandbox Code Playgroud)

孩子

<template>
  <button
    class="own-button"
    type="button"
    @click="emit('ownButtonClicked')"
    v-on:keyup.enter="emit('ownButtonClicked')"
  >
    <slot> 
    </slot>
  </button>
</template>

<script setup>

const emit = defineEmits
([
  'ownButtonClicked'
]);
</script>

<style scoped>
.own-button
{
  background-color  : azure;
  outline-color     : lightblue;
  color             : black;
  margin            : 2px;
  padding           : 5px;
  border-radius     : 15px;
  border            : 0;
  box-shadow        : 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
  outline-style     : solid;
  min-width         : 100px;
  max-width         : 150px;
}
.own-button:hover
{
  cursor: pointer;
}
</style>
Run Code Online (Sandbox Code Playgroud)

我尝试了我能想到的一切,包括在父级中使用 :deep(button)

rol*_*oli 6

这是 Vue 3 在处理多根节点时的设计限制

我在我的文章“作用域样式和多根节点不能很好地协同工作”中写到了这一点。

了解问题

在 Vue 3 中,我们终于可以拥有多个“一个根节点”组件了。这很好,但是这样做存在设计限制。想象我们有一个子组件:

<template>
  <p class="my-p">First p</p>
  <p class="my-p">Second p</p>
</template>
Run Code Online (Sandbox Code Playgroud)

和一个父组件:

<template>
    <h1>My awesome component</h1>
    <MyChildComponent />
</template>

<style scoped>
// There is no way to style the p tags of MyChildComponent
.my-p { color: red; }
:deep(.my-p) { color: red; }
</style>
Run Code Online (Sandbox Code Playgroud)

无法从多根父组件的作用域样式来设置子组件的 p 标签的样式。

简而言之,多根组件无法使用作用域样式来定位多根子组件的样式。

解决方案

解决这个问题的最佳方法是包装父组件或子组件(或两者),这样我们就只有一个根元素。

但如果您绝对需要两者都具有多根节点,您可以:

  1. 使用无范围样式
<style>
.my-p { color: red; }
</style>
Run Code Online (Sandbox Code Playgroud)
  1. 使用 CSS 模块
<template>
    <h1>My awesome component</h1>
    <MyChildComponent :class="$style.trick" />
</template>

<style module>
.trick {
    color: red;
}
</style>
Run Code Online (Sandbox Code Playgroud)

由于我们在这里指定一个类,因此多根子组件必须显式指定属性fallthrough行为。



如果您想听听我的意见,除非您绝对需要多根节点组件,否则请使用单个根节点,并且根本不处理此设计限制。