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.