I am working on a Vue3 component. According to the design, there are two slightly different variations of the layout, a simplified example:
- Two inner components in the top row, slot below them
<div class="flex flex-col">
<div class="flex">
<InnerComponent1/>
<InnerComponent2/>
</div>
<slot/>
</div>
- Two inner components in the left column, slot on the right
<div class="flex flex-col">
<div class="flex">
<InnerComponent1/>
<slot/>
</div>
<InnerComponent2/>
</div>
What is the right way to implement this in Vue 3? One obvious way is to pass a layout
property, then just duplicate the whole div with v-if="layout === 'type1'"
etc., but this doesn’t look good, there will be a lot of code duplication.
You could create each layout as its own component replacing all content with slots. Then use a dynamic component to choose which layout to use at runtime. Insert the desired content into each slot, and then let the dynamic component handle the layout of those slots.
LayoutA.vue
<template>
<div class="flex flex-col">
<div class="flex">
<slot name="inner1" />
<slot name="inner2" />
</div>
<slot />
</div>
</template>
LayoutB.vue
<template>
<div class="flex flex-col">
<div class="flex">
<slot name="inner1" />
<slot />
</div>
<slot name="inner2" />
</div>
</template>
Component.vue
<template>
<component :is="layout">
<template #inner1>
<InnerComponent1 />
</template>
<template #inner2>
<InnerComponent2 />
</template>
<template #default>
<slot />
</template>
</component>
</template>
<script setup>
import LayoutA from './LayoutA.vue';
import LayoutB from './LayoutB.vue';
const layout = ... // insert logic here that decides LayoutA or LayoutB
</script>