Computed adalah nilai yang dihitung dari data reaktif lain, dan Vue mengingat hasilnya sampai salah satu bahannya berubah. Bayangin papan tulis di kasir Warung Bu Sri. Begitu pesanan masuk, Bu Sri menghitung totalnya sekali dan menulisnya di papan. Kalau pembeli bertanya "berapa totalnya?" lima kali, Bu Sri cukup membaca papan, gak menghitung ulang. Dia baru menghitung lagi kalau jumlah porsi atau harganya berubah. Papan itu computed. Kasir yang menghitung ulang tiap kali ditanya, itu method.
🧪 Tebakan cepat: Template menampilkan
{{ total }}di dua tempat.totaladalah computed darihargadanjumlah. Pembeli menekan tombol "Tambah catatan" tiga kali, jadi halaman render ulang tiga kali, tapihargadanjumlahgak berubah. Sejak halaman tampil, berapa kali fungsitotaldijalankan? Tebak dulu, jawabannya ada di bagian "Computed mengingat hasilnya".
Nilai turunan dengan computed()
const harga = ref(15000)
const jumlah = ref(2)
const total = computed(() => harga.value * jumlah.value)
---template---
<p>Nasi Goreng × {{ jumlah }}</p>
<p>Total: Rp{{ total }}</p>
<button @click="jumlah++">+1 porsi</button>
| Kejadian | jumlah |
total |
|---|---|---|
| Halaman tampil | 2 | 30000 |
| Klik +1 porsi | 3 | 45000 |
| Klik +1 porsi | 4 | 60000 |
computed(() => ...)menerima sebuah fungsi yang mengembalikan nilai, disebut getter. Hasilnya ref yang cuma bisa dibaca.- Di dalam getter, data reaktif tetap dibaca lewat
.value. Hasilnya dibacatotal.valuedi script, dan cukup{{ total }}di template. - Vue mencatat data reaktif apa saja yang dibaca getter, di sini
hargadanjumlah. Itu dependency-nya. Begitu salah satunya berubah,totaldihitung ulang. - Latihan memakai pola yang sama:
computed(() => harga.value * jumlah.value)dengan 50000 dan 3 menghasilkan150000, dancomputed(() => firstName.value + " " + lastName.value)menghasilkanBudi Santoso. Spasi di tengah ikut dirangkai. - Di proyek sungguhan, import keduanya:
import { ref, computed } from "vue". Di editor latihan sudah tersedia.
Getter wajib mengembalikan nilai
// salah: kurung kurawal tanpa return, total jadi undefined
const total = computed(() => { harga.value * jumlah.value })
// benar: tanpa kurung kurawal, hasilnya langsung dikembalikan
const total = computed(() => harga.value * jumlah.value)
// benar juga: kurung kurawal dengan return
const total = computed(() => {
return harga.value * jumlah.value
})
- Arrow function dengan kurung kurawal gak mengembalikan apa-apa kalau gak ada
return. Computed-nya bernilaiundefined, dan{{ total }}tampil kosong, tanpa error.
Computed mengingat hasilnya
const harga = ref(15000)
const jumlah = ref(2)
const catatan = ref("")
const total = computed(() => {
console.log("computed total dihitung")
return harga.value * jumlah.value
})
function hitungTotal() {
console.log("method hitungTotal dipanggil")
return harga.value * jumlah.value
}
---template---
<p>Total: Rp{{ total }} · Bayar: Rp{{ total }}</p>
<p>Total: Rp{{ hitungTotal() }} · Bayar: Rp{{ hitungTotal() }}</p>
<p>Catatan: {{ catatan }}</p>
<button @click="catatan += 'pedas '">Tambah catatan</button>
<button @click="jumlah++">+1 porsi</button>
| Kejadian | total (computed) dijalankan |
hitungTotal() (method) dipanggil |
|---|---|---|
| Render pertama | 1 | 2 |
| Tambah catatan, render ulang | 0, pakai hasil yang diingat | 2 |
| Tambah catatan, render ulang | 0 | 2 |
| Tambah catatan, render ulang | 0 | 2 |
+1 porsi, jumlah berubah |
1 | 2 |
Sejak halaman tampil sampai klik catatan ketiga, total cuma dijalankan sekali, walau dipakai di dua tempat dan halaman render empat kali. Itu jawaban tebakannya. Kemampuan mengingat hasil ini namanya caching, keunggulan utama computed dibanding fungsi biasa. Method dipanggil ulang di setiap render, sekali per tempat dia dipakai.
- Pakai computed untuk nilai yang diturunkan dari data reaktif: total, nama lengkap, daftar yang difilter.
- Pakai method kalau hasilnya memang harus baru tiap render, misalnya jam sekarang.
const jam = computed(() => Date.now())yang ditampilkan di template gak pernah berubah, karenaDate.now()bukan data reaktif, jadi gak ada dependency yang memicu hitung ulang.
📌 Computed yang bisa ditulis
Computed biasa cuma bisa dibaca. total.value = 0 gak mengubah apa-apa, dan build development menulis [Vue warn] Write operation failed: computed value is readonly. Kalau memang perlu ditulis, beri computed sebuah get dan set:
const firstName = ref("Budi")
const lastName = ref("Santoso")
const fullName = computed({
get: () => firstName.value + " " + lastName.value,
set: (baru) => {
const [depan, belakang] = baru.split(" ")
firstName.value = depan
lastName.value = belakang
},
})
fullName.value = "Siti Aminah"
// firstName.value = "Siti", lastName.value = "Aminah"
getdipakai saatfullNamedibaca, sama seperti getter biasa.setdipanggil saatfullName.valuediberi nilai. Dia gak menyimpan hasilnya sendiri, tapi mengubah data sumbernya, lalugetmenghitung ulang dari situ.
⚠️ Jebakan yang sering ketemu
- Kurung kurawal tanpa
return. Computed-nyaundefineddan tampil kosong. Hapus kurung kurawalnya atau tambahkanreturn. - Menyimpan hasil di variabel biasa.
const total = harga.value * jumlah.valuedihitung sekali saat script jalan.jumlahberubah,totaltetap. Latihan memeriksa bahwa kodenya memanggilcomputed(...). - Lupa
.valuedi dalam getter.harga * jumlahmengalikan dua kotak ref, bukan angkanya, hasilnyaNaN. - Mengubah data di dalam getter. Getter cuma boleh menghitung dan mengembalikan nilai. Menaikkan
jumlahatau memanggil server di dalamnya membuat hasilnya kacau. Taruh perubahan seperti itu di method.
TL;DR: const total = computed(() => harga.value * jumlah.value) membuat nilai turunan yang dihitung ulang otomatis saat harga atau jumlah berubah. Di script dibaca total.value, di template cukup {{ total }}. Keunggulan utamanya caching: hasilnya diingat dan getter-nya gak dijalankan lagi sampai dependency-nya berubah, sedangkan method dipanggil di setiap render. Getter dengan kurung kurawal wajib return. Computed biasa cuma bisa dibaca; untuk menulisnya, beri get dan set.