Вложенные "двунаправленные" слоты во Vuejs
Я использую Vuejs. Я создал два компонента:First
а также Second
.
First
оказываетSecond
.Second
имеет именованный слот.First
содержит<template>
, идти вSecond
названный слот.- Внутри
First
с<template>
- есть еще один именованный слот. - Внутри
Second
с<slot>
- E сть<template>
, идти вFirst
с<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
Могу ли я добиться этого с помощью слотов? Если нет, можно ли этого добиться другим способом, но без создания третьего компонента?
РЕДАКТИРОВАТЬ: возможный реальный вариант использования: компонент 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 ответ
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>