Comprehensive Guide to Parent-Child Component Communication in Vue 3

Data Flow from Parent to Child Using Props

Passing Static Values

When passing fixed string literals to a child component, the v-bind directive (shorthand :) is not required.

<DashboardWidget
  app-name="Analytics Hub"
  current-release="2.4"
/>

Inside the child component, declare the expected properties using defineProps.

const properties = defineProps({
  appName: String,
  currentRelease: String
})

To access these values within the template, use the variable names directly. How ever, in the script block, you must reference them through the props object.

<!-- Template usage -->
<h3>{{ appName }} - v{{ currentRelease }}</h3>
// Script usage
console.log('Current version is:', properties.currentRelease)

Passing Dynamic Reactive Data

To pass reactive data dynamically, you must use the v-bind directive (:). This establishes a reactive connection between the parent's state and the child's props.

<script setup>
import { ref, reactive } from 'vue'

const accountBalance = ref(5000)
const clientInfo = reactive({
  alias: 'John Doe',
  accessLevel: 3
})
</script>

<template>
  <FinancialReport
    :balance="accountBalance"
    :user="clientInfo"
  />
  <button @click="accountBalance += 500">Add Funds</button>
</template>

In the child component, define the props and observe their reactivity.

const properties = defineProps({
  balance: Number,
  user: Object
})

watch(() => properties.balance, (updatedVal) => {
  console.log('Balance changed to:', updatedVal)
})
<p>Available balance: {{ balance }}</p>
<p>User: {{ user.alias }}, Level: {{ user.accessLevel }}</p>

Whenever the parent updates accountBalance, the child component automatically reflects the change in the template and triggers any associated watchers.

Communicating from Child to Parent via Events

To send data upward, the child component emits custom events, which the parent listens to using the v-on directive (@).

Basic Event Emission

In the child component, declare and trigger events using defineEmits.

<!-- TransactionPanel.vue -->
<script setup>
const dispatch = defineEmits(['notifyDeposit'])

const processTransaction = () => {
  dispatch('notifyDeposit', 250)
}
</script>

<template>
  <button @click="processTransaction">Send Funds to Parent</button>
</template>

The parent component captures the emitted event and executes a handler method.

<!-- MainApp.vue -->
<template>
  <TransactionPanel @notify-deposit="handleDeposit" />
  <p>Total Funds: {{ totalFunds }}</p>
</template>

<script setup>
import { ref } from 'vue'
const totalFunds = ref(0)

const handleDeposit = (amount) => {
  totalFunds.value += amount
}
</script>

TypeScript Event Definitions

For strict typing in TypeScript, define the event signatures explicitly.

const dispatch = defineEmits<{
  (e: 'notifyDeposit', amount: number): void
  (e: 'submitProfile', payload: { alias: string }): void
}>()

// Usage
dispatch('submitProfile', { alias: 'Jane Smith' })

Practical Example: Inventory Management

A complete scenario demonstrating two-way communication for managing a list of gadgets.

<!-- InventoryManager.vue -->
<template>
  <GadgetList
    :stock="inventoryList"
    @delete-gadget="handleDelete"
    @adjust-stock="handleStockAdjustment"
  />
</template>

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

const inventoryList = ref([
  { id: 1, name: 'Tablet', quantity: 15 },
  { id: 2, name: 'Laptop', quantity: 8 }
])

const handleDelete = (gadgetId) => {
  inventoryList.value = inventoryList.value.filter(item => item.id !== gadgetId)
}

const handleStockAdjustment = ({ id, newQty }) => {
  const targetItem = inventoryList.value.find(item => item.id === id)
  if (targetItem) targetItem.quantity = newQty
}
</script>

<!-- GadgetList.vue -->
<script setup>
defineProps({
  stock: Array
})

const dispatch = defineEmits(['deleteGadget', 'adjustStock'])

const removeItem = (gadgetId) => {
  dispatch('deleteGadget', gadgetId)
}

const changeQuantity = (gadgetId, newQty) => {
  dispatch('adjustStock', { id: gadgetId, newQty })
}
</script>

Tags: vue3 defineProps defineEmits Component Communication Composition API

Posted on Mon, 08 Jun 2026 16:03:40 +0000 by PHPNewbie55