Вложенные «двунаправленные» слоты в Vuejs - PullRequest
0 голосов
/ 04 февраля 2020

Я использую Vuejs. Я создал два компонента: First и Second.

  1. First рендеринг Second.
  2. Second имеет именованный слот.
  3. First содержит <template>, до go в названном слоте Second.
  4. Внутри First s <template> - есть еще один названный слот.
  5. Внутри Second s <slot> - есть <template>, до go в First s <template> названном слоте.

То, что я получаю First '<template> отображается в слоте Second.

Это правильно, но я бы хотел также видеть Second' * <template>, отображаемый внутри <slot> из First ' с <template>. Но я не знаю.

Вот код:

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

Могу ли я добиться этого с помощью слотов? Если нет, то может ли это быть достигнуто другим способом, но без создания третьего компонента?

EDIT : возможный реальный сценарий использования: компонент 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>

1 Ответ

1 голос
/ 04 февраля 2020

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>

отсутствуют, поскольку * slot2 или какой-либо слот не определен внутри компонента slot, поэтому ваш 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...