I took this example from Vue SFC Playground and added a Transition. The problem is that in order for the transition to work, I need to provide the div with the changing key () but that breaks the KeepAlive. The CompA and CompB component reloads as if there is no KeepAlive.
<script setup>
import { shallowRef, } from 'vue'
import CompA from './CompA.vue'
import CompB from './CompB.vue'
const current = shallowRef(CompA)
</script>
<template>
<div class="demo">
<label><input type="radio" v-model="current" :value="CompA" /> A</label>
<label><input type="radio" v-model="current" :value="CompB" /> B</label>
<br/>Curent:{{current.__name}}
<Transition mode="out-in">
<div :key="current.__name">
<KeepAlive>
<component :is="current" :key="current.__name"></component>
</KeepAlive>
</div>
</Transition>
</div>
</template>
<style>
.v-enter-active,
.v-leave-active {
transition: opacity 0.5s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
</style>
///CompA.vue:
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<p>Current component: A</p>
<span>count : {{ count }}</span>
<button @click="count++">+</button>
</template>
///CompB.vue:
<script setup>
import { ref } from 'vue'
const msg = ref('')
</script>
<template>
<p>Current component: B</p>
<span>Message is: {{ msg }}</span>
<input v-model="msg">
</template>
<Transition>
needs the actual components to have a single root element. Simply wrap your CompA and CompB templates with a div, then remove the div between Transition and KeepAlive
<Transition mode="out-in">
<KeepAlive>
<component :is="current" :key="current.__name"></component>
</KeepAlive>
</Transition>
CompA.vue:
<template>
<div>
<p>Current component: A</p>
<span>count : {{ count }}</span>
<button @click="count++">+</button>
</div>
</template>
CompB.vue:
<template>
<div>
<p>Current component: B</p>
<span>Message is: {{ msg }}</span>
<input v-model="msg">
</div>
</template>