Vue.js嵌套插槽:如何将插槽传递给孙子

时间:2018-11-22 12:10:42

标签: vue.js vuejs2 vuetify.js

我使用了不同的vuetify组件,例如v-menu。它具有这样的模板:

<v-menu>
  <a slot="activator">menu</a>
  <v-list>
    <v-list-tile>Menu Entry 1</v-list-tile>
    <v-list-tile>Menu Entry 2</v-list-tile>
  </v-list>
</v-menu>

假设我要在其周围添加另一个包装器。那是我的特殊菜单组件,具有一些预定义的菜单选项。我也希望它也有一个激活器插槽。最后一个应该以某种方式分配给原始的v菜单激活器插槽。有可能吗?

示例:

// index.vue: 
<template>
  <my-special-menu>
    <button>My special menu trigger</button>
  </my-special-menu>
</template>

// MySpecialMenu.vue
<template>
  <v-menu>
    <slot slot="activator"/> <-- I don't know how to write this line
    <v-list>...</v-list>
  </v-menu>
</template>

<slot slot="activator">是不正确的等式。目标是从父级(在示例中为<button>..</button>)提取内容,并将其用作v菜单中的slot="activator"

我可以这样写:

<v-menu>
  <a slot="activator"><slot/></a>
  ...
</v-menu>

但是在这种情况下,结果模板将是:

<div class="v-menu__activator">
  <a>
    <button>My special menu trigger</button>
  </a>
</div>

那不是我想要的。是否可以在这里摆脱<a>包装器?

更新: 我们可以使用类似<template slot="activator"><slot name="activator"/></template>的结构来给孙子孙女扔一些槽。但是,如果我们有多个插槽并希望全部代理它们该怎么办?就像对于插槽来说,是InheritAttrs和v-bind="$attrs"。目前有可能吗?

例如,vuetify中有一个<v-autocomplete>组件,它具有附加,前置,标签,无数据,进度,项目,选择等插槽。我为此写了一些包装器组件,它看起来像:

<template>
  <v-autocomplete ..>
    <template slot="append"><slot name="append"/></template>
    <template slot="prepend"><slot name="prepend"/></template>
    <template slot="label"><slot name="label"/></template>
    ...
    <template slot="item" slot-scope="props"><slot name="item" v-bind="props"/></template>
  </v-autocomplete>
</template>

是否可以避免在此处枚举所有插槽?

1 个答案:

答案 0 :(得分:8)

如果将slot属性放在html元素上,则该html元素将传递到子组件,以使用该名称填充广告位。如果您不想传递html元素,则可以在组件中的slot标签上使用template。模板标记可对元素进行分组,但不能呈现为html元素,这在这里很完美。您还可以将模板标签用于其他用途,例如将v-if中的元素分组,或使用v-for重复多个元素。

// App.vue
<template>
  <div id="app">
    <test>
      <template slot="activator">
        Click <b>me</b>!
      </template>
    </test>
  </div>
</template>
// Test.vue
<template>
  <div class="wrapper">
    <grand-child>
      <template slot="activator">
        <slot name="activator"></slot>
      </template>
    </grand-child>

    This is some text
  </div>
</template>
// GrandChild.vue
<template>
  <div>
    <a href="#" @click="toggle = !toggle">
      <slot name="activator">Default</slot>
    </a>

    <div v-if="toggle">This appears and disappears</div>
  </div>
</template>

Edit Vue Template

编辑:如果要对任意插槽执行此操作,这也是可能的。 this.$slots包含广告位及其内容,因此,可以使用以下类似内容将广告位内容传递给具有相同名称的广告位:

<grand-child>
  <template v-for="(_, slot) in $slots">
    <template :slot="slot">
      <slot :name="slot"></slot>
    </template>
  </template>
</grand-child>

Edit Vue Template

相关问题