Props — Vue

Menerima Props // Di komponen child, gunakan defineProps const props = defineProps(["title", "count"]) ---template--- {{ title }} {{ count }} Props dengan…

Props adalah data yang dikirim parent ke child lewat atribut di tag child-nya. Bayangin tempat label harga di etalase Warung Bu Sri. Bentuk tempat labelnya sama semua, tapi Bu Sri menyelipkan kertas yang beda ke tiap tempat: "Nasi Goreng, 15000", "Es Teh, 5000". Tempat label itu cuma menampilkan isi kertasnya. Kalau harganya mau diganti, Bu Sri yang menulis kertas baru, bukan tempat labelnya. Tempat label itu komponen child, kertasnya props, dan Bu Sri parent-nya.

🧪 Tebakan cepat: MenuCard menyatakan harga: Number dan menampilkan Dibungkus: Rp{{ harga + 2000 }}. Parent menulis <MenuCard nama="Nasi Goreng" harga="15000" />, tanpa titik dua di depan harga. Apa yang tampil? Tebak dulu, jawabannya ada di bagian "Titik dua: teks atau nilai JavaScript".

Parent mengirim, child menerima

Child menyatakan props apa saja yang dia terima dengan defineProps:

<!-- MenuCard.vue -->
<script setup>
const props = defineProps({
  nama: String,
  harga: Number,
  stok: Number,
})
</script>

<template>
  <div class="kartu">
    <h3>{{ nama }}</h3>
    <p>Rp{{ harga }}</p>
    <small>Stok: {{ stok }}</small>
  </div>
</template>

Parent mengisinya lewat atribut, satu tag satu salinan:

<!-- App.vue -->
<script setup>
import MenuCard from "./MenuCard.vue"
</script>

<template>
  <MenuCard nama="Nasi Goreng" :harga="15000" :stok="8" />
  <MenuCard nama="Mie Ayam" :harga="12000" :stok="0" />
  <MenuCard nama="Es Teh" :harga="5000" :stok="20" />
</template>
Tag di App.vue Yang tampil
nama="Nasi Goreng" :harga="15000" :stok="8" Nasi Goreng, Rp15000, Stok: 8
nama="Mie Ayam" :harga="12000" :stok="0" Mie Ayam, Rp12000, Stok: 0
nama="Es Teh" :harga="5000" :stok="20" Es Teh, Rp5000, Stok: 20

Titik dua: teks atau nilai JavaScript

Teks ditambah angka di JavaScript berarti disambung, bukan dijumlah. "15000" + 2000 jadi "150002000", jadi kartunya menulis Dibungkus: Rp150002000. Itu jawaban tebakannya. Dengan :harga="15000", hasilnya Dibungkus: Rp17000.

Build development memberi tahu kesalahannya: [Vue warn]: Invalid prop: type check failed for prop "harga". Expected Number with value 15000, got String with value "15000". Editor latihan memakai build production, jadi warning seperti ini gak muncul di sana. Angka yang aneh itu satu-satunya petunjuk.

Tipe, required, dan default

Tiap prop bisa diberi aturan:

const props = defineProps({
  nama: { type: String, required: true },
  harga: { type: Number, required: true },
  stok: { type: Number, default: 0 },
  catatan: { type: Array, default: () => [] },
})

Props cuma bisa dibaca

Data mengalir satu arah: dari parent ke child. Child boleh membaca props, gak boleh mengubahnya.

<!-- MenuCard.vue, cara yang salah -->
<button @click="stok--">Beli 1</button>

📌 Nama prop dua kata

Di script, nama prop ditulis camelCase: hargaPromo. Di template parent, biasanya ditulis kebab-case: <MenuCard :harga-promo="13000" />. Vue menganggap harga-promo dan hargaPromo prop yang sama, jadi keduanya jalan.

File .vue dan editor latihan

Editor latihan menjalankan satu komponen: script, garis ---template---, lalu template. Child ditulis sebagai objek di script, dan dipasang dengan <component :is>:

const MenuCard = {
  props: {
    nama: String,
    harga: Number,
    stok: Number,
  },
  template: `
    <div class="kartu">
      <h3>{{ nama }}</h3>
      <p>Rp{{ harga }}</p>
      <small>Stok: {{ stok }}</small>
    </div>
  `,
}

---template---
<div>
  <component :is="MenuCard" nama="Nasi Goreng" :harga="15000" :stok="8" />
  <component :is="MenuCard" nama="Es Teh" :harga="5000" :stok="20" />
</div>
Di file .vue Di editor latihan
defineProps({ ... }) di MenuCard.vue opsi props: { ... } di objek MenuCard
<template> milik MenuCard.vue opsi template berupa teks di antara backtick
import MenuCard from "./MenuCard.vue" lalu <MenuCard ... /> <component :is="MenuCard" ... />

⚠️ Jebakan yang sering ketemu

TL;DR: Props adalah data dari parent ke child. Child menyatakannya dengan defineProps({ nama: String, harga: Number }), parent mengirimnya lewat atribut: <MenuCard nama="Nasi Goreng" :harga="15000" />. Tanpa titik dua yang dikirim teks, dengan titik dua nilai JavaScript. type, required, dan default mengatur aturannya, dan default array atau objek ditulis sebagai fungsi. Props cuma bisa dibaca: data mengalir satu arah, dan perubahannya dilakukan parent. Di editor latihan, child ditulis sebagai objek dengan opsi props dan template, lalu dipasang dengan <component :is="MenuCard">.

Yang akan kamu pelajari