JAVASCRIPT

Parent-Child Communication with defineProps and defineEmits in Vue 3

Pass data down with `defineProps` and send events up with `defineEmits` for effective parent-child communication in Vue 3 `script setup`. Master component interaction.

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

const parentMessage = ref('Hello from Parent!');
const childName = ref('Alice');
const receivedMessageFromChild = ref('');

const handleChildEvent = (message) => {
  receivedMessageFromChild.value = `Child says: "${message}"`;
};
</script>

<template>
  <div>
    <h1>Parent Component</h1>
    <p>Parent Message: {{ parentMessage }}</p>
    <p>Received from Child: {{ receivedMessageFromChild }}</p>

    <!-- Passing props down and listening for custom events up -->
    <ChildComponent
      :message="parentMessage"
      :userName="childName"
      @child-said-hello="handleChildEvent"
    />

    <button @click="parentMessage = 'Updated message from Parent!'">Update Parent Message</button>
  </div>
</template>

// --- ChildComponent.vue ---
<script setup>
import { defineProps, defineEmits } from 'vue';

// Define props with type validation and default values
const props = defineProps({
  message: {
    type: String,
    required: true,
    default: 'Default message'
  },
  userName: {
    type: String,
    default: 'Guest'
  },
  age: Number // Simple type declaration
});

// Define custom events that this component can emit
const emit = defineEmits(['child-said-hello', 'update:userName']); // 'update:propName' is for v-model

const greetParent = () => {
  emit('child-said-hello', `Hi Parent, it's ${props.userName}!`);
};

// This function is commented out in template, but demonstrates how to emit 'update:userName'
// const changeUserNameInChild = () => {
//   emit('update:userName', 'Bob (changed by child)');
// };
</script>

<template>
  <div style="border: 1px solid blue; padding: 10px; margin-top: 10px;">
    <h2>Child Component</h2>
    <p>Prop Message from Parent: {{ props.message }}</p>
    <p>Prop User Name: {{ props.userName }}</p>
    <button @click="greetParent">Greet Parent</button>
    <!-- <button @click="changeUserNameInChild">Change User Name (via emit)</button> -->
    <p>(Check parent component to see emitted message)</p>
  </div>
</template>
How it works: This snippet demonstrates the essential pattern for parent-child communication in Vue 3 using the `script setup` syntax. It comprises two files: `ParentComponent.vue` and `ChildComponent.vue`. The parent component passes data down to the child using props, defined in the child with `defineProps` for type validation and defaults. The child component communicates back to the parent by emitting custom events using `defineEmits`, which the parent then listens for using `@` syntax. This unidirectional data flow ensures predictable state management.

Need help integrating this into your project?

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

Hire DigitalCodeLabs