Optimasi Performa Vue dengan Key, Lazy Rendering, dan Watch Effect

Ketika aplikasi Vue mulai tumbuh dan memiliki banyak komponen, masalah performa bisa muncul tanpa disadari, tampilan terasa lambat, re-render yang tidak perlu, atau proses komputasi yang berat terus berjalan di background. Vue sebenarnya sudah sangat efisien secara default, tetapi ada beberapa fitur dan teknik penting yang dapat membantu kita menjaga performa aplikasi tetap optimal, terutama dalam proyek skala menengah hingga besar.

Dalam artikel ini, kita akan membahas tiga konsep penting yang sering menjadi kunci dalam optimasi performa Vue:

  1. Penggunaan atribut key untuk efisiensi render list
  2. Teknik Lazy Rendering (Penundaan Render) agar UI tidak membebani DOM
  3. Pemanfaatan watchEffect untuk reaktivitas yang efisien dan selektif

1. Pentingnya key untuk Optimasi Rendering

Vue menggunakan Virtual DOM untuk memperbarui tampilan dengan efisien. Namun, ketika kita menampilkan daftar elemen menggunakan v-for, Vue perlu tahu bagaimana membedakan setiap item dalam daftar. Di sinilah atribut key berperan.

Tanpa key, Vue akan mencoba memperbarui elemen DOM secara “cerdas” berdasarkan posisi — tapi kadang hasilnya tidak sesuai harapan. Misalnya, ketika item dihapus atau ditambahkan di tengah daftar, Vue bisa saja mengubah isi elemen lama alih-alih membuat ulang elemen baru. Ini bisa menimbulkan bug tampilan.

Contoh Tanpa key

<template>
  <ul>
    <li v-for="item in items">{{ item.name }}</li>
  </ul>
</template>

<script setup>
const items = [
  { id: 1, name: 'A' },
  { id: 2, name: 'B' },
  { id: 3, name: 'C' }
]
</script>

Jika item dihapus atau urutan berubah, Vue mungkin “menukar” elemen tanpa benar-benar merender ulang.

Contoh Dengan key yang Benar

<template>
  <ul>
    <li v-for="item in items" :key="item.id">{{ item.name }}</li>
  </ul>
</template>

Dengan :key, Vue tahu persis elemen mana yang berubah, sehingga hanya bagian yang perlu diperbarui yang akan di-render ulang.

Tips Praktis:

  • Gunakan nilai unik dan stabil, seperti id database.
  • Jangan gunakan index array (:key="index") kecuali list benar-benar statis.
  • Penggunaan key yang konsisten mencegah re-render penuh dan meningkatkan kinerja UI besar seperti tabel dinamis atau daftar panjang.

2. Lazy Rendering: Render Hanya Saat Diperlukan

Lazy Rendering atau penundaan render berarti kita hanya menampilkan elemen saat benar-benar dibutuhkan.
Konsep ini sangat penting untuk halaman yang panjang, daftar komponen besar, atau tampilan dengan banyak tab.

Kasus Umum Tanpa Lazy Rendering

Bayangkan kita memiliki tiga tab besar dalam satu halaman, masing-masing dengan 20 komponen di dalamnya. Jika kita menulis:

<template>
  <div>
    <TabA />
    <TabB />
    <TabC />
  </div>
</template>

Semua tab akan di-render sekaligus walaupun hanya satu yang ditampilkan. Ini jelas membuang sumber daya.


Menggunakan v-if untuk Lazy Render

<template>
  <div>
    <button @click="active = 'A'">Tab A</button>
    <button @click="active = 'B'">Tab B</button>
    <button @click="active = 'C'">Tab C</button>

    <TabA v-if="active === 'A'" />
    <TabB v-if="active === 'B'" />
    <TabC v-if="active === 'C'" />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import TabA from './TabA.vue'
import TabB from './TabB.vue'
import TabC from './TabC.vue'

const active = ref('A')
</script>

Dengan v-if, hanya tab yang aktif saja yang dirender.
Ketika pengguna berpindah tab, Vue akan membuang komponen lama dari DOM dan membuat ulang yang baru.

Namun, jika kita ingin menyimpan state komponen (misalnya form tetap terisi ketika kembali ke tab sebelumnya), gunakan v-show atau kombinasi dengan <keep-alive>.


Kombinasi v-show dan <keep-alive>

<template>
  <keep-alive>
    <TabA v-show="active === 'A'" />
    <TabB v-show="active === 'B'" />
    <TabC v-show="active === 'C'" />
  </keep-alive>
</template>

Dengan pendekatan ini:

  • v-show hanya menyembunyikan komponen tanpa menghapusnya dari DOM.
  • <keep-alive> memastikan state komponen tetap tersimpan, misalnya input atau scroll position.

Kesimpulan:
Gunakan v-if untuk komponen berat yang jarang digunakan, dan v-show dengan keep-alive untuk tampilan yang sering berpindah tetapi ingin mempertahankan state.


3. Optimasi Reaktivitas dengan watchEffect

Vue memiliki sistem reaktivitas yang pintar — ia akan secara otomatis memperbarui komponen saat data berubah. Tapi jika tidak hati-hati, kita bisa memicu re-render yang tidak perlu, terutama jika ada banyak watch atau computed kompleks.

Di Vue 3, watchEffect() memberikan kontrol yang lebih efisien atas apa yang perlu “dipantau” secara reaktif.


Cara Kerja watchEffect

watchEffect menjalankan fungsi dan otomatis melacak dependensi reaktif yang digunakan di dalamnya.
Setiap kali salah satu dependensi berubah, fungsi itu akan dijalankan ulang.

<script setup>
import { ref, watchEffect } from 'vue'

const count = ref(0)
const doubled = ref(0)

watchEffect(() => {
  doubled.value = count.value * 2
})
</script>

Setiap kali count berubah, Vue akan menjalankan kembali fungsi di dalam watchEffect.


Perbedaan watch dan watchEffect

FiturwatchwatchEffect
Mengamati variabel tertentuYa, spesifikTidak, otomatis berdasarkan penggunaan
Akses nilai lama & baruYaTidak
Waktu inisialisasiTidak langsung jalanLangsung dijalankan sekali
Penggunaan umumReaksi terhadap data tertentuEfek samping otomatis (misalnya update UI, sync data)

Contoh Optimasi dengan watchEffect

Misalnya kita ingin memantau filter pencarian tanpa harus men-trigger request setiap kali pengguna mengetik satu huruf.
Kita bisa mengombinasikan watchEffect dengan setTimeout untuk debounce:

<script setup>
import { ref, watchEffect } from 'vue'

const search = ref('')
const results = ref([])

watchEffect(() => {
  const timeout = setTimeout(() => {
    if (search.value.trim() !== '') {
      console.log('Fetching data for:', search.value)
      // Lakukan request API di sini
    }
  }, 500)

  return () => clearTimeout(timeout) // cleanup
})
</script>

<template>
  <input v-model="search" placeholder="Cari produk..." />
</template>

Dengan pendekatan ini, API hanya dipanggil setelah 500ms pengguna berhenti mengetik — menghemat sumber daya dan mempercepat respons UI.


4. Kombinasi Ketiganya dalam Skenario Nyata

Misalkan kita membuat aplikasi daftar produk e-commerce dengan ribuan item. Kita bisa menggabungkan ketiga teknik di atas:

  • Gunakan :key di v-for agar list efisien saat data berubah.
  • Terapkan Lazy Rendering untuk tab atau filter berat seperti kategori dan rekomendasi.
  • Gunakan watchEffect untuk memantau filter pencarian dan update data dengan optimal.

Contoh Sederhana

<template>
  <div>
    <input v-model="search" placeholder="Cari produk..." />

    <div v-if="filteredProducts.length === 0">
      Tidak ada hasil.
    </div>

    <ul>
      <li v-for="product in filteredProducts" :key="product.id">
        {{ product.name }}
      </li>
    </ul>
  </div>
</template>

<script setup>
import { ref, computed, watchEffect } from 'vue'

const products = ref([
  { id: 1, name: 'Laptop' },
  { id: 2, name: 'Keyboard' },
  { id: 3, name: 'Mouse' },
  { id: 4, name: 'Monitor' },
])

const search = ref('')
const filteredProducts = ref([])

watchEffect(() => {
  filteredProducts.value = products.value.filter(p =>
    p.name.toLowerCase().includes(search.value.toLowerCase())
  )
})
</script>

Vue hanya akan memperbarui list yang relevan — cepat, efisien, dan mudah dipahami.


5. Tips Tambahan untuk Optimasi Performa

  • Gunakan v-once untuk elemen statis yang tidak berubah.
  • Manfaatkan computed untuk perhitungan berat, bukan di template langsung.
  • Hindari loop bersarang dan gunakan pagination jika list terlalu panjang.
  • Gunakan dynamic import atau code-splitting dengan defineAsyncComponent untuk komponen besar yang jarang digunakan.

Optimasi performa di Vue tidak selalu berarti menulis kode yang rumit — cukup memahami bagaimana Vue bekerja dan memanfaatkan fitur yang sudah disediakan dengan tepat.

  • key membantu Vue membedakan dan memperbarui elemen DOM dengan efisien.
  • Lazy Rendering memastikan hanya bagian yang dibutuhkan yang dirender, menghemat sumber daya.
  • watchEffect memberi kita kontrol penuh terhadap kapan dan bagaimana efek reaktif dijalankan.

Dengan menggabungkan ketiganya, aplikasi Vue akan terasa lebih ringan, responsif, dan tetap mudah dipelihara seiring bertambahnya kompleksitas.