Vue.js Lesson 7: Events & Emit
Child components communicate with parents by emitting events. This is the Vue way of passing data up the component tree.
defineEmits
<script setup>
// Child component
const emit = defineEmits(["add-to-cart", "favorite", "remove"]);
function handleBuy() {
emit("add-to-cart", { id: product.id, qty: 1 });
}
function handleFavorite() {
emit("favorite", product.id);
}
</script>
<template>
<button @click="handleBuy">Add to Cart</button>
<button @click="handleFavorite">♥</button>
</template>
<!-- Parent listens with @ -->
<template>
<ProductCard
:product="p"
@add-to-cart="onAddToCart"
@favorite="onFavorite"
/>
</template>
<script setup>
function onAddToCart(item) {
cart.value.push(item);
}
</script>
v-model on Components
<!-- Custom input using v-model -->
<!-- SearchBox.vue -->
<template>
<input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
</template>
<script setup>
defineProps(["modelValue"]);
defineEmits(["update:modelValue"]);
</script>
<!-- Usage in parent -->
<SearchBox v-model="searchQuery" />
<!-- equivalent to -->
<SearchBox :modelValue="searchQuery" @update:modelValue="searchQuery = $event" />
🏋️ Practice Task
Build a todo list app with components. TodoItem: shows text, checkbox, delete button. Emits: “toggle” (id), “delete” (id). TodoList: v-for of TodoItems, handles emits to update parent array. TodoForm: v-model text input + Add button. Emits “add” (text). Wire in App.vue.
💡 Hint: In App.vue: const todos = ref([]). @add=”todos.push({id:Date.now(),text:$event,done:false})”. @delete=”todos=todos.filter(t=>t.id!==$event)”