• Fri, Mar 2026

Emitting Events from Child to Parent in Vue.js

This in-depth tutorial explores how to emit events from child to parent in Vue.js.It guides you step by step with practical examples, professional explanations, and best practices. Whether you’re new to Vue or polishing your advanced skills, this guide will make parent-child communication in Vue.js crystal clear.

Introduction

When I first started with Vue.js, I felt like a parent trying to understand my teenager’s cryptic text messages. The child component knew everything but refused to share it directly with me (the parent component). That’s when I discovered the magic of emitting events in Vue.js. Suddenly, communication was smooth, controlled, and predictable.

This article will walk you through the concept of child-to-parent communication using $emit in Vue.js, from basics to advanced techniques, with step-by-step code examples.

What Does Emitting Events Mean in Vue.js?

In Vue.js, components follow a unidirectional data flow: data usually goes from parent to child using props. But sometimes, the child component needs to send information back. Instead of directly modifying parent data, Vue uses events to keep things clean and decoupled.

Real-Life Analogy

Think of it like this: a child raises their hand (emits an event), and the parent decides how to respond (listens and acts). This separation keeps responsibilities clear.

Step 1: Setting Up the Vue Environment

Let’s start with a basic Vue 3 project using Vite. Run these commands in your terminal:

npm init vue@latest vue-event-demo
cd vue-event-demo
npm install
npm run dev

This creates a Vue app ready for development.

Step 2: Creating Parent and Child Components

We’ll create two components: ParentComponent.vue and ChildComponent.vue.

Child Component

<template>
  <button @click="notifyParent">Click Me</button>
</template>

<script setup>
import { defineEmits } from 'vue';

const emit = defineEmits(['childClicked']);

function notifyParent() {
  emit('childClicked', 'The child says hello!');
}
</script>

Parent Component

<template>
  <div>
    <h2>Parent Component</h2>
    <ChildComponent @childClicked="handleChildEvent" />
    <p>Message: {{ message }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const message = ref('');

function handleChildEvent(payload) {
  message.value = payload;
}
</script>

In this simple example, the child emits childClicked, and the parent listens for it.

Step 3: Understanding the emit Mechanism

The emit function allows the child to send signals to the parent. Here’s the breakdown:

  • defineEmits: Declares which events a component can emit.
  • emit('eventName', data): Triggers the event with optional data.
  • @eventName: The parent listens using Vue’s event binding.

Step 4: Passing Data from Child to Parent

Events are powerful because you can attach data. For instance, when a user fills a form in the child component, you can pass the form data to the parent.

Child Component with Input

<template>
  <div>
    <input v-model="username" placeholder="Enter your name" />
    <button @click="submitForm">Submit</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { defineEmits } from 'vue';

const username = ref('');
const emit = defineEmits(['formSubmitted']);

function submitForm() {
  emit('formSubmitted', username.value);
}
</script>

Parent Component

<template>
  <div>
    <h2>Form Example</h2>
    <ChildComponent @formSubmitted="receiveFormData" />
    <p>User entered: {{ user }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const user = ref('');

function receiveFormData(data) {
  user.value = data;
}
</script>

Step 5: Multiple Events

A child component can emit multiple events. For example:

<script setup>
import { defineEmits } from 'vue';

const emit = defineEmits(['saved', 'deleted']);

function save() {
  emit('saved', { status: 'success' });
}

function remove() {
  emit('deleted', { status: 'removed' });
}
</script>

Step 6: Event Naming Best Practices

  • Use kebab-case for event names (e.g., user-logged-in).
  • Be descriptive but concise.
  • Avoid generic names like event.

Step 7: Handling Events with Arguments

You can pass multiple arguments by emitting an object:

emit('userUpdated', { id: 1, name: 'Alice', role: 'Admin' });

Parent:

<ChildComponent @userUpdated="updateHandler" />

function updateHandler(user) {
  console.log('Updated user:', user);
}

Step 8: Dynamic Events

You can dynamically decide which event to emit:

function trigger(eventType) {
  emit(eventType, 'Some payload');
}

Step 9: Event Modifiers

Vue supports event modifiers when listening in the parent:

<ChildComponent @childClicked.stop="handleChildEvent" />

This stops event propagation.

Step 10: Debugging Emitted Events

Use Vue Devtools to inspect events. Under the “Events” tab, you’ll see every event emitted with its payload. This makes debugging straightforward.

Step 11: Comparing Props vs Emits

Props pass data down; emits send events up. Here’s a comparison:

DirectionPropsEmits
Data FlowParent ? ChildChild ? Parent
Use CaseProviding initial data, configurationsCommunicating actions, results

Step 12: Advanced Example - Todo App

Let’s build a mini todo app. The child handles adding tasks, and the parent manages the list.

Child Component

<template>
  <div>
    <input v-model="task" placeholder="New task" />
    <button @click="addTask">Add</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { defineEmits } from 'vue';

const task = ref('');
const emit = defineEmits(['taskAdded']);

function addTask() {
  if (task.value.trim() !== '') {
    emit('taskAdded', task.value);
    task.value = '';
  }
}
</script>

Parent Component

<template>
  <div>
    <h2>Todo App</h2>
    <ChildComponent @taskAdded="addNewTask" />
    <ul>
      <li v-for="(item, index) in tasks" :key="index">{{ item }}</li>
    </ul>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const tasks = ref([]);

function addNewTask(task) {
  tasks.value.push(task);
}
</script>

Conclusion

By now, you should feel confident about emitting events from child to parent in Vue.js. We’ve explored the basics of $emit, passing data, handling multiple events, using best practices, and building practical examples like forms and todo apps.

Next time you’re working on a Vue.js project, remember: props send data down, emits send events up. This simple rule will keep your components clean and your development experience smoother.

So go ahead—let your child components raise their hands proudly, and let the parent respond wisely.

This website uses cookies to enhance your browsing experience. By continuing to use this site, you consent to the use of cookies. Please review our Privacy Policy for more information on how we handle your data. Cookie Policy