【问题标题】:Nested "bi-directional" slots in VuejsVuejs 中嵌套的“双向”插槽
【发布时间】:2020-05-19 19:22:49
【问题描述】:

我正在使用 Vuejs。 我创建了两个组件:FirstSecond

  1. First 渲染 Second
  2. Second 有一个命名槽。
  3. First 包含一个<template>,用于进入Second 的命名槽。
  4. First<template> 内部 - 还有另一个命名槽。
  5. Second<slot> 内部 - 有一个<template>,用于进入First<template> 的命名槽。

我得到的是First<template> 渲染在Second 的插槽内。

这是正确的,但我还希望看到Second<template> 呈现在First<template><slot> 内。但我没有。

代码如下:

var First = Vue.extend({
  template: `
    <div>
      In first<br/>
      <second>
        <template slot="slot1">
          In template of First
          <slot name="slot2">
          </slot>
        </template>
      </second>
    </div>
  `
})
Vue.component('first', First)

var Second = Vue.extend({
  template: `
    <div>
      In second<br/>
      <slot name="slot1">
        <template slot="slot2">
          In template of Second
        </template>
      </slot>
    </div>
  `
})
Vue.component('second', Second)

这是输出:

In first
In second
In template of First

这里是 jsfiddle:https://jsfiddle.net/obeobe/f98kr4ye/

我想得到这个输出:

In first
In second
In template of First
In template of Second

我可以通过插槽实现这一点吗?如果没有,是否可以通过其他方式实现,但无需创建第三个组件?

编辑:一个可能的现实用例:一个 List 组件,它允许每个项目的 HTML 内容由其宿主定义,并且可以在宿主的内部注入一些自己的内容内容,在主持人指定的地点。

例如,像这样的:

主机组件:

<div class="myList">
    <list v-bind:items="usersArray">
        <template slot="itemSlot" slotScope="item">
            <div>{{ item.name }}</div>
            <div>{{ item.country }}</div>
            <div>{{ item.phone }}</div>
            <slot name="actions"> <--------- the spot for the List component to inject generic actions
            </slot>
            <div>{{ item.age }}</div>
        </template>
    </list>
</div>

“列表”组件:

<div>
    <div v-for="(anItem, idx) in items">
        <div>{{ idx }}</div>
        <slot name="itemSlot" v-bind:item="anItem">
            <template slot="actions">
                <a v-on:click="duplicateItem(anItem)">Duplicate</a> <---------- the "duplicateItem" method would be implemented inside this List component
                <a>Edit</a>
                <a>Delete</a>
            </template>
        </slot>
    </div>
</div>

【问题讨论】:

  • 嗨@obe 我只是添加我的答案,这听起来有点傻,所以不确定我是否正确理解你的情况。

标签: vue.js vuejs-slots


【解决方案1】:

AFAIK,Vue.js 中没有双向插槽

<div id="app">
  <first>
         ─────────────────────┐
  </first>                    │
</div>                        │
                              │
<div>                         │
  In first<br/>               │
  <second>                    │
    <template slot="slot1">  ─────┐
      In template of First    │   │
      <slot name="slot2">  <──┘ ┄┄│┄┄> This slot will replaced by slot2
      </slot>                     │    template child of first component.
    </template>                   │
  </second>                       │
</div>                            │
                                  │
<div>                             │
  In second<br/>                  │
  <slot name="slot1">  <──────────┘
    <template slot="slot2">  ┄┄┄┄┄┄┄┄> This is fallback content it will 
      In template of Second            shows up if no content provided.
    </template>                        But slot template is used so
                                       this will go to replace slot2
                                       inside slot.
  </slot>
</div>

由于没有slot2slot 组件内定义的任何插槽,因此您的In template of Second 永远不会出现。

在你的例子中,我认为没有办法做到这一点。实现这一目标的另一种方法是通过插槽范围绑定duplicateItem

<div class="myList">
  <list v-bind:items="usersArray">
    <template slot="itemSlot" slotScope="{ item, duplicateItem }">
      <div>{{ item.name }}</div>
      <div>{{ item.country }}</div>
      <div>{{ item.phone }}</div>
      <div>
        <a v-on:click="duplicateItem(item)">Duplicate</a>
        <a>Edit</a>
        <a>Delete</a>
      </div>
      <div>{{ item.age }}</div>
    </template>
  </list>
</div>

<div>
  <div v-for="(anItem, idx) in items">
    <div>{{ idx }}</div>
      <slot name="itemSlot"
        v-bind:item="anItem"
        v-bind:duplicateItem="duplicateItem">
      </slot>
    </div>
  </div>
</div>

【讨论】:

  • 谢谢,但我需要它...我只是分享了一个简化版本...
  • @obe 你能详细解释一下吗?
  • 是的,我编辑了我的问题并添加了一个更详细的示例。我希望它能让事情更清楚......
  • @obe 我已经更新了我的答案,您可能已经想到了这种方法,但我认为这是最好的方法。
  • 是的,但我希望 List 组件也可以处理动作的 HTML...它在不同的地方一次又一次地重复,所以 List 组件拥有通用的会很方便操作区域的一部分 - HTML、逻辑和 CSS。无论如何,你的答案不是我所希望的圣杯,但我相信它正确地回答了我的问题,因为 Vuejs 不允许这样做,并且它包含一个有效的建议,所以我接受它。谢谢!
猜你喜欢
  • 2019-04-25
  • 2023-01-07
  • 2019-06-08
  • 2018-08-09
  • 1970-01-01
  • 2018-07-28
  • 2022-09-29
  • 2018-02-21
  • 2022-01-09
相关资源
最近更新 更多