JAVASCRIPT

Vue 3 Component Communication: Props and Emits

Understand how to pass data down with `defineProps` and emit events up with `defineEmits` for effective communication between parent and child components in Vue 3.

<!-- ParentComponent.vue -->
<template>
  <div>
    <h1>Parent Component</h1>
    <p>Message from Child: {{ childMessage }}</p>
    <p>Parent Counter: {{ parentCounter }}</p>

    <ChildComponent
      :title="parentTitle"
      :initial-count="parentCounter"
      @send-message="handleChildMessage"
      @increment-parent-count="incrementParentCount"
    />
  </div>
</template>

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

const parentTitle = ref('Data for Child');
const parentCounter = ref(10);
const childMessage = ref('');

const handleChildMessage = (message) => {
  childMessage.value = message;
  console.log('Received message from child:', message);
};

const incrementParentCount = (value) => {
  parentCounter.value += value;
  console.log('Parent counter incremented by child:', value);
};
</script>

<!-- ChildComponent.vue -->
<template>
  <div class="child-container">
    <h2>Child Component</h2>
    <p>Prop Title: {{ title }}</p>
    <p>Initial Count (Prop): {{ initialCount }}</p>
    <button @click="sendMessageToParent">Send Message to Parent</button>
    <button @click="emitIncrementEvent">Increment Parent Counter by 2</button>
  </div>
</template>

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

// Define props for receiving data from parent
const props = defineProps({
  title: {
    type: String,
    required: true
  },
  initialCount: {
    type: Number,
    default: 0
  }
});

// Define emits for sending events to parent
const emit = defineEmits(['send-message', 'increment-parent-count']);

const sendMessageToParent = () => {
  emit('send-message', 'Hello from Child Component!');
};

const emitIncrementEvent = () => {
  emit('increment-parent-count', 2); // Pass a value with the event
};
</script>

<style scoped>
.child-container {
  border: 1px solid #ccc;
  padding: 15px;
  margin-top: 20px;
  background-color: #f9f9f9;
}
</style>
How it works: In Vue 3, `defineProps` and `defineEmits` are compilers macros used within `<script setup>` for robust component communication. `defineProps` declares the props a component expects to receive from its parent, ensuring type validation and providing default values. Data flows downwards via props (one-way data flow). `defineEmits` declares the custom events a component can emit to its parent, allowing the child to communicate upwards. When an event is emitted, the parent component can listen for it using `v-on:` (or `@`) and react with a handler function. This parent-child communication pattern is fundamental for building modular and reusable Vue applications.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs