Transition & Komponen Dinamis
Animasi masuk/keluar dengan <Transition> dan <TransitionGroup>, kelas transisi, mode out-in, komponen dinamis <component :is>, KeepAlive, dan Teleport.
Animasi tanpa JavaScript rumit
Saat elemen muncul atau hilang karena v-if, tampilan terasa kasar jika langsung berubah. Vue menyediakan komponen bawaan <Transition> yang menempelkan kelas CSS pada fase masuk dan keluar, sehingga kamu cukup menulis CSS-nya.
Transition dasar
<button @click="tampil = !tampil">Toggle</button>
<Transition name="fade">
<p v-if="tampil" class="pesan">Halo!</p>
</Transition>
<style>
.fade-enter-active, .fade-leave-active { transition: opacity 0.4s ease; }
.fade-enter-from, .fade-leave-to { opacity: 0; }
</style>
<Transition> hanya boleh membungkus satu elemen/komponen dan bereaksi pada v-if, v-show, atau perubahan :is/key.
| Kelas | Fase |
|---|---|
nama-enter-from | Awal masuk (dihapus setelah 1 frame) |
nama-enter-active | Selama masuk (tempat menaruh transition) |
nama-enter-to | Akhir masuk |
nama-leave-from | Awal keluar |
nama-leave-active | Selama keluar |
nama-leave-to | Akhir keluar |
Tanpa atribut name, awalan kelasnya v- (v-enter-from, dst.).
Mode peralihan
Saat mengganti satu elemen dengan elemen lain, keduanya bisa tampil bersamaan. Atur dengan mode="out-in" (yang lama keluar dulu, baru yang baru masuk).
<Transition name="fade" mode="out-in">
<component :is="tabAktif" />
</Transition>
TransitionGroup untuk daftar
<TransitionGroup name="daftar" tag="ul">
<li v-for="item in items" :key="item.id">{{ item.nama }}</li>
</TransitionGroup>
.daftar-enter-active, .daftar-leave-active { transition: all 0.4s; }
.daftar-enter-from, .daftar-leave-to { opacity: 0; transform: translateX(30px); }
.daftar-move { transition: transform 0.4s; } /* animasi saat item bergeser */
TransitionGroup membutuhkan :key unik pada setiap anak dan dapat membungkus dengan elemen lewat tag.
Komponen dinamis: <component :is>
Untuk menukar komponen berdasarkan data (tab, wizard, widget), pakai elemen khusus <component :is="...">.
<script setup>
import { shallowRef } from 'vue'
import TabA from './TabA.vue'
import TabB from './TabB.vue'
const tabAktif = shallowRef(TabA) // shallowRef: jangan jadikan komponen reaktif
</script>
<template>
<button @click="tabAktif = TabA">A</button>
<button @click="tabAktif = TabB">B</button>
<component :is="tabAktif" />
</template>
Simpan komponen dengan shallowRef (atau markRaw). Membungkusnya dengan ref biasa membuat Vue mencoba menjadikannya reaktif secara mendalam — boros dan memunculkan peringatan.
KeepAlive: menyimpan state komponen
Secara bawaan, komponen yang ditukar dihancurkan, sehingga isiannya hilang. Bungkus dengan <KeepAlive> untuk menyimpannya di memori.
<KeepAlive>
<component :is="tabAktif" />
</KeepAlive>
Hook khusus: onActivated dan onDeactivated.
Teleport: merender di tempat lain
Modal sebaiknya berada langsung di <body> agar tidak terpotong CSS induknya. <Teleport to="body"> memindahkan hasil render tanpa memutus hubungan logika.
<Teleport to="body">
<div v-if="buka" class="modal">...</div>
</Teleport>
Kesalahan umum
- Membungkus lebih dari satu elemen di dalam
<Transition>. - Lupa
:keypada anakTransitionGroup. - Memakai
refuntuk komponen pada:is(pakaishallowRef).