您想要做的事情称为“复合组件”。
您需要使用provide/inject(相当于Vue中的ReactContext)并让carousel-group知道carousel-panel已放入其中。
我使用表组件中的 registerChild 来执行此操作。我从我的仓库中获取了这个https://github.com/sethidden/vue-compound-components/tree/master/example-table https://github.com/sethidden/vue-compound-components/tree/master/example-table
<!-- MyTable.vue -->
<script setup>
import {ref, provide, defineProps } from 'vue'
const props = defineProps({
items: {
type: Array,
required: true,
}
})
const registerChild = (child) => registeredChildren.value.push(child);
const unregisterChild = (child) => {
registeredChildren.value =
registeredChildren.value.filter(
registeredChild => registeredChild !== child
);
};
const registeredChildren = ref([]);
provide('TheParent', { registerChild, unregisterChild })
</script>
<template>
columns: {{ registeredChildren.map(x=>x.itemPropertyName) }}
<table>
<thead>
<tr>
<th v-for="column in registeredChildren" :key="column">
<component :is="column.content" ref="column"/>
{{ column.sortable ? 'sortable' : ''}}
</th>
</tr>
</thead>
<tbody>
<tr v-for="item, i in items" :key="i">
<td v-for="column, j in registeredChildren" :key="j">
{{ item[column.itemPropertyName] }}
</td>
</tr>
</tbody>
</table>
<!-- we want the mounted() lifecycle to fire on the components that are in the slot, but we dont want to show them -->
<div v-show="false">
<slot/>
</div>
</template>
<!-- MyTableColumn.vue -->
<script setup>
import {onMounted,onBeforeUnmount,inject, defineProps, h, render, useContext} from 'vue'
const props = defineProps({
itemPropertyName: {
type: String,
required: true,
},
sortable: {
type: Boolean,
default: false
}
})
const { registerChild, unregisterChild } = inject('TheParent');
const ctx = useContext();
const childInfo = {
itemPropertyName: props.itemPropertyName,
sortable: props.sortable,
// since ctx.slots.default is a render fn,
// we pass slot content from here to the parent component
// then render it in the parent using <component :is=""/>
content: ctx.slots.default
}
registerChild(childInfo);
onBeforeUnmount(() => {
unregisterChild(childInfo);
})
</script>
<template>
<div>
<slot/>
</div>
</template>
显然,这是一个表格组件,但您明白了 - 您可以通过在安装上注册哪些面板来跟踪哪些面板位于轮播组内,并使用来自父级的某些属性,这要归功于inject()
另一件事是您想要管理哪个轮播面板处于活动状态。哪个面板处于活动状态显然会保留在轮播组中,但您还需要使用以下命令切换面板的可见性v-for="panes in registeredChildren" v-if="activePane === pane.id"
,但这可以通过以下方式实现:
<carousel-group>
<carousel-pane id="1"/>
<carousel-pane id="2"/>
<carousel-pane id="3"/>
</carousel-group>
然后让轮播组的内部数据属性从来自 RegisteredChildren 的第一个窗格开始,然后在 5 秒后更改为第二个窗格,依此类推。
https://github.com/3nuc/vue-compound-components/blob/master/example-dropdown/Example.vue https://github.com/3nuc/vue-compound-components/blob/master/example-dropdown/Example.vue