Vue.js 3 中的插槽继承

Slot Inheritance in Vue.js 3

我正在尝试理解 how/if 我可以在 Vue.js v3 中定义某种插槽继承。我有一个 Container class 定义了 2 个槽:titleitems。我在 Grid class 中扩展了 Container,并在其中定义了 items 插槽。当我去使用我的 Grid class 时,我想定义 title 插槽。 Fiddle供参考。

Container.vue

<template>
  <div>
    <header v-if="showTitle">
      <slot name="title" />
    </header>

    <main v-if="showItems">
      <slot name="items" />
    </main>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "MyContainer",
  computed: {
    showTitle() {
      return !!this.$slots.title;
    },
    showItems() {
      return !!this.$slots.items;
    },
  },
});
</script>

Grid.vue

<template>
  <MyContainer>
    <template #items>
      <span>Here are my items</span>
    </template>
  </MyContainer>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import MyContainer from "@/components/base/Container";

export default defineComponent({
  name: "MyGrid",
  extends: MyContainer,
  components: { MyContainer },
});
</script>

App.vue

<template>
  <div id="app">
    <MyGrid>
      <!-- How can I pass this along to MyGrid's base class? -->
      <template #title>
        <span>This is my title!</span>
      </template>
    </MyGrid>
  </div>
</template>

<script>
import MyGrid from "@/components/base/Grid";

export default {
  name: "App",
  components: {
    MyGrid,
  },
};
</script>

问题出在 App.vue 中,我在模板中有评论——我想传递其中定义的插槽。这可能吗?

根据 this,我必须定义一个模板,该模板基本上传递实例上定义的任何插槽。所以在我的 Grid.vue class 中,我会添加以下代码:

<template>
  <MyContainer>
    <template #items>
      <span>Here are my items</span>
    </template>
    <!-- Added this template -->
    <template v-for="(_, name) in $slots" v-slot:[name]="slotData">
      <slot :name="name" v-bind="slotData" />
    </template>
  </MyContainer>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import MyContainer from "@/components/base/Container";

export default defineComponent({
  name: "MyGrid",
  extends: MyContainer,
  components: { MyContainer },
});
</script>

Grid 组件中定义标题槽,然后在其中使用 component 动态呈现其 children :

 <MyContainer>
    <template #title>
      <component v-for="(el, i) in $slots.title()" :is="el" :key="i">
      </component>
    </template>
    <template #items>
      <span>Here are my items</span>
    </template>
  </MyContainer>
</template>

DEMO