У меня есть модальный компонент, который выглядит так
//modal component
<template>
<slot></slot>
<slot name='buttons'></slot>
</template>
Я хочу использовать его как мастер
//wizard component
<template>
<modal>
<step1-state v-if='step === 1'/>
<step2-state v-if='step === 2'/>
</modal>
</template>
Есть ли способ, которым шаги step1, step2 и т.д. Используют слот для buttons
?
Это, похоже, не работает
//step1-state component
<template>
<div>
<span>Does it work?</span>
<div slot='buttons'>
<button>yes</button>
<button>no</button>
</div>
</div>
</template>
После некоторых исследований я обнаружил, что это невозможно по умолчанию. Я смог добиться этого с помощью пользовательских функций рендеринга.
child-slot
компонент - это нужно разместить внутри содержимого родительского слота, он позволяет вам форматировать содержимое дочернего компонента. Вы можете добавить несколько child-slot
для смешивания с родительским контентом. Он должен определить атрибут ref
с отличным значением.
компонент use-slot
- этот используется для указания того, какой контент должен быть передан родительскому контенту в качестве содержимого child-slot
. Содержимое будет размещено внутри элемента span
. Ему нужны named
и container
атрибуты.
named
- имя слота для размещения контента в
container
- значение ref
для child-slot
use-slot
автоматически найдет первый родительский слот, названный named
атрибуту, независимо от глубины ребенка
ребенок-слот
<script>
export default {
render(createElement) {
return createElement('span', {}, this.content);
},
data() {
return {
nodesToRender: {}
}
},
computed: {
content() {
var result = [];
for (var node in this.nodesToRender) {
result = result.concat(this.nodesToRender[node] || []);
}
return result;
}
}
}
</script>
Использование слота
<script>
export default {
abstract: true,
props: {
named: {
type: String,
required: true
},
container: {
type: String,
required: true
}
},
render() {
var parent = this.findParentOfSlot();
var content = this.$slots.default;
var self = this;
this.$parent.$nextTick(function () {
if (parent && parent.$refs && parent.$refs[self.container], parent.$refs[self.container].nodesToRender) {
Vue.set(parent.$refs[self.container].nodesToRender, self.$vnode.tag, content);
}
});
},
methods: {
findParentOfSlot() {
var parent = this.$parent;
while (parent) {
if (parent.$slots && parent.$slots[this.named]) {
return parent.$parent;
}
parent = parent.$parent;
}
return parent;
}
}
}
</script>
Насколько мне известно, это невозможно в настоящее время и не имеет особого смысла, потому что оно становится сложным и трудным для чтения. Представьте себе, глядя на такой гнездовый слот через 3 месяца после его написания. Если оба ваши ступенчатые компоненты требуют этого buttons
слота затем записать его как собрат рядом с ними и отправить реквизит каждый раз, когда у вас есть изменения из этой buttons
слота
Кстати, кажется, что есть компонент мастера https://github.com/cristijora/vue-form-wizard, случайно написанный мной))
step1-state
иstep2-state
использоватьmodal
напрямую, а затем просто использоватьdiv
или что-то еще в качестве оболочки вwizard
?