Emits — Vue

Mengirim Event ke Parent const emit = defineEmits(["update", "delete"]) const handleClick = () => { emit("update", "data baru") } ---template--- Update Hapus…

Emit adalah cara child mengirim kabar ke parent: "barusan ada yang terjadi di sini". Props turun dari parent ke child, event naik dari child ke parent. Bayangin pembeli di depan kartu menu Warung Bu Sri yang menekan bel "Tambah". Kartu menu gak memegang keranjang, jadi dia gak bisa menambah pesanan sendiri. Dia cuma membunyikan bel sambil bilang "Nasi Goreng, 15000". Kasir yang mendengar bel itu yang mencatat ke keranjang. Kartu menu itu child, belnya event, dan kasir parent-nya.

🧪 Tebakan cepat: MenuCard memanggil emit("tambah") waktu tombolnya diklik, tapi App.vue memasang <MenuCard /> tanpa @tambah. Waktu tombolnya diklik: error merah, warning, atau gak terjadi apa-apa? Tebak dulu, jawabannya ada di bagian "Parent mendengarkan dengan @".

Child mengirim event dengan emit

<!-- MenuCard.vue -->
<script setup>
const props = defineProps({ nama: String, harga: Number })
const emit = defineEmits(["tambah"])

function klikTambah() {
  emit("tambah", props.nama, props.harga)
}
</script>

<template>
  <div class="kartu">
    <h3>{{ nama }}</h3>
    <p>Rp{{ harga }}</p>
    <button @click="klikTambah">Tambah</button>
  </div>
</template>

Parent mendengarkan dengan @

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

const jumlah = ref(0)
const total = ref(0)

function tambahKeKeranjang(nama, harga) {
  jumlah.value++
  total.value += harga
  console.log("Masuk keranjang:", nama)
}
</script>

<template>
  <MenuCard nama="Nasi Goreng" :harga="15000" @tambah="tambahKeKeranjang" />
  <MenuCard nama="Es Teh" :harga="5000" @tambah="tambahKeKeranjang" />
  <p>Keranjang: {{ jumlah }} item, Rp{{ total }}</p>
</template>
Klik Payload yang sampai jumlah total Console
awal 0 0
Tambah di Nasi Goreng "Nasi Goreng", 15000 1 15000 Masuk keranjang: Nasi Goreng
Tambah di Nasi Goreng "Nasi Goreng", 15000 2 30000 Masuk keranjang: Nasi Goreng
Tambah di Es Teh "Es Teh", 5000 3 35000 Masuk keranjang: Es Teh

Props turun, event naik

Di pelajaran props, child gak boleh mengubah stok. Emit adalah jalan keluarnya: child melapor, parent yang mengubah.

<!-- MenuCard.vue, di template -->
<small>Stok: {{ stok }}</small>
<button @click="$emit('beli')">Beli 1</button>

<!-- App.vue, di template -->
<MenuCard nama="Mie Ayam" :stok="stok" @beli="stok--" />

Klik Beli 1: child mengirim beli, parent mengurangi ref stok miliknya, lalu angka baru turun lagi ke child lewat :stok. Datanya tetap punya satu pemilik.

📌 Nama event dan validasi

File .vue dan editor latihan

Di editor, child ditulis sebagai objek dengan opsi emits, dan dipasang dengan <component :is>:

const jumlah = ref(0)
const total = ref(0)

function tambahKeKeranjang(nama, harga) {
  jumlah.value++
  total.value += harga
  console.log("Masuk keranjang:", nama)
}

const MenuCard = {
  props: { nama: String, harga: Number },
  emits: ["tambah"],
  template: `
    <div class="kartu">
      <h3>{{ nama }}</h3>
      <p>Rp{{ harga }}</p>
      <button @click="$emit('tambah', nama, harga)">Tambah</button>
    </div>
  `,
}

---template---
<div>
  <component :is="MenuCard" nama="Nasi Goreng" :harga="15000" @tambah="tambahKeKeranjang" />
  <component :is="MenuCard" nama="Es Teh" :harga="5000" @tambah="tambahKeKeranjang" />
  <p>Keranjang: {{ jumlah }} item, Rp{{ total }}</p>
</div>
Di file .vue Di editor latihan
const emit = defineEmits(["tambah"]) opsi emits: ["tambah"]
emit("tambah", ...) di script $emit('tambah', ...) di template child, atau emit dari setup(props, { emit })
<MenuCard @tambah="..." /> <component :is="MenuCard" @tambah="..." />

⚠️ Jebakan yang sering ketemu

TL;DR: Emit mengirim kabar dari child ke parent. Child menyatakan event-nya dengan const emit = defineEmits(["tambah"]) lalu memanggil emit("tambah", nama, harga); argumen sesudah nama event adalah payload. Parent mendengarkan dengan @tambah="handler", dan payload sampai sebagai argumen handler. Event tanpa listener hilang tanpa error. Props turun, event naik: child melapor, parent yang mengubah datanya. Di editor latihan, child ditulis sebagai objek dengan emits: ["tambah"] dan $emit(...) di template-nya, lalu dipasang dengan <component :is>.

Yang akan kamu pelajari