Reactivity: ref & reactive
Membuat data reaktif dengan ref() dan reactive(), aturan .value, unwrapping di template, perbedaan keduanya, dan pembaruan DOM yang asinkron.
Mengapa butuh reactivity?
Coba ubah variabel biasa:
<script setup>
let jumlah = 0
function tambah() { jumlah++ } // jumlah bertambah, tapi layar TIDAK berubah
</script>
Variabel JavaScript biasa tidak "dipantau" Vue. Agar Vue tahu kapan data berubah dan memperbarui tampilan, data harus dibuat reaktif.
ref(): membungkus satu nilai
<script setup>
import { ref } from 'vue'
const jumlah = ref(0)
function tambah() {
jumlah.value++ // di script: pakai .value
}
</script>
<template>
<button @click="tambah">Klik: {{ jumlah }}</button> <!-- di template: tanpa .value -->
</template>
ref(0) mengembalikan objek { value: 0 } yang dipantau Vue. Aturan emasnya:
| Di mana | Cara mengakses |
|---|---|
Di <script> | jumlah.value |
Di <template> | jumlah (otomatis "dibuka" / unwrapped) |
ref bisa menampung tipe apa pun: angka, string, boolean, array, bahkan objek.
const nama = ref('Budi')
const aktif = ref(false)
const daftar = ref(['apel', 'jeruk'])
daftar.value.push('mangga') // push ke array juga reaktif
reactive(): objek yang reaktif
Untuk kumpulan data berbentuk objek, reactive() lebih ringkas karena tidak perlu .value.
import { reactive } from 'vue'
const profil = reactive({ nama: 'Budi', umur: 20 })
function ulangTahun() {
profil.umur++ // langsung, tanpa .value
}
ref atau reactive?
| ref | reactive | |
|---|---|---|
| Menampung | Nilai apa pun | Hanya objek/array/Map/Set |
| Akses di script | x.value | x.properti |
| Ganti seluruh nilai | x.value = baru ✅ | x = baru ❌ (reaktivitas putus) |
| Destructuring | Aman | Memutus reaktivitas (pakai toRefs) |
Saran: pakai ref sebagai pilihan default (dokumentasi resmi Vue pun menyarankannya). Gunakan reactive bila kamu ingin sekumpulan properti berkaitan tanpa mengetik .value.
Jebakan reactive: const { umur } = profil mengambil angka biasa — reaktivitas hilang. Untuk memecah dengan aman gunakan toRefs(profil).
DOM diperbarui secara asinkron
Saat data berubah, Vue tidak langsung mengubah DOM, tetapi mengumpulkan perubahan lalu menerapkannya sekali di "tick" berikutnya agar efisien. Jika kamu butuh membaca DOM setelah diperbarui, gunakan await nextTick().
import { ref, nextTick } from 'vue'
const teks = ref('a')
async function ubah() {
teks.value = 'b'
await nextTick()
// DOM sudah menampilkan 'b'
}
Kesalahan umum
- Lupa
.valuedi script:jumlah++mengubah objek ref, bukan angkanya. - Menulis
.valuedi template:{{ jumlah.value }}tidak diperlukan (dan salah). - Mengganti objek
reactivedengan=. Ubah propertinya, atau pakairef.