๐ Vue.js Props: The Gift Box Story
The Magic of Unwrapping Gifts
Imagine you receive a gift box ๐ from your friend. Inside the box, thereโs a toy car, a puzzle, and some candy. In Vue.js, this gift box is called props โ things a parent component gives to a child component.
Now, hereโs the exciting part: How do you take things out of the box?
๐ฆ What Are Props Destructuring Caveats?
The Story
Think of props like a magic gift box that keeps changing. If you take the toy out and put it on your shelf, your toy on the shelf wonโt magically change when someone puts a NEW toy in the gift box!
<!-- โ The Problem: Breaking the Magic Connection -->
<script setup>
const { count } = defineProps(['count'])
// count is just a NUMBER now (like 5)
// It's NOT connected to the gift box anymore!
// If the box updates, your shelf doesn't know
</script>
What Happens Here?
- You open the gift box (
defineProps) - You take
countout and put it on your shelf - The gift box gets a new count? Your shelf still has the old one!
๐ฎ The Magic Solution: Reactive Props Destructure
Vue 3.5+ Gave Us Magic Powers!
Starting from Vue 3.5, when you destructure props in <script setup>, the magic connection stays alive!
<!-- โ
Vue 3.5+: The Magic Connection Stays! -->
<script setup>
const { count } = defineProps(['count'])
// Now count IS reactive!
// When gift box updates, your shelf updates too!
</script>
graph TD A["๐ Parent Component"] -->|Sends Props| B["๐ฆ defineProps"] B -->|Vue 3.5+ Magic| C["โจ Reactive count"] C -->|Auto Updates| D["๐ฅ๏ธ Your Template"] style A fill:#4CAF50,color:#fff style B fill:#2196F3,color:#fff style C fill:#FF9800,color:#fff style D fill:#9C27B0,color:#fff
โ ๏ธ The Caveats (Watch Out!)
Caveat 1: Default Values Need Special Care
<script setup>
// โ This default won't be reactive
const { count = 0 } = defineProps(['count'])
// โ
Use withDefaults for reactive defaults
const props = withDefaults(
defineProps<{ count?: number }>(),
{ count: 0 }
)
</script>
Why? Default values are like putting a placeholder toy on your shelf. The placeholder isnโt connected to the gift box!
Caveat 2: Passing to Functions
<script setup>
const { count } = defineProps(['count'])
// โ ๏ธ Be careful when passing to functions!
watch(
// โ This loses reactivity
count,
(newVal) => console.log(newVal)
)
watch(
// โ
Use a getter to keep reactivity
() => count,
(newVal) => console.log(newVal)
)
</script>
๐จ Real Examples
Example 1: A Counter Display
<!-- ParentComponent.vue -->
<template>
<ChildDisplay :score="playerScore" />
</template>
<script setup>
import { ref } from 'vue'
const playerScore = ref(100)
</script>
<!-- ChildDisplay.vue -->
<script setup>
const { score } = defineProps(['score'])
// score updates when parent changes it! โจ
</script>
<template>
<div class="score-box">
๐ Score: {{ score }}
</div>
</template>
Example 2: User Profile Card
<!-- ProfileCard.vue -->
<script setup>
const {
name,
avatar,
isOnline
} = defineProps(['name', 'avatar', 'isOnline'])
</script>
<template>
<div class="card">
<img :src="avatar" />
<h3>{{ name }}</h3>
<span :class="isOnline ? 'green' : 'gray'">
{{ isOnline ? '๐ข Online' : 'โซ Offline' }}
</span>
</div>
</template>
๐ Quick Comparison Table
| Situation | Vue < 3.5 | Vue 3.5+ |
|---|---|---|
const { x } = defineProps() |
โ Not reactive | โ Reactive |
| Default values | โ Problem | โ ๏ธ Use withDefaults |
In watch() |
Use getter () => x |
Use getter () => x |
| In template | โ Works | โ Works |
๐ง Remember This!
The Gift Box Rule ๐
When you destructure props in Vue 3.5+, the magic connection stays alive. But always use getters in functions like
watch()to keep the connection working!
Simple Mental Model
๐ฆ Props = Gift Box (always changing)
๐ Destructured = Items on your shelf
๐ฎ Vue 3.5+ = Magic shelf that updates automatically!
โ ๏ธ Functions = Need special getter wrapper
๐ฏ Key Takeaways
- Props Destructuring = Taking items out of the gift box
- Vue 3.5+ = The magic connection stays alive
- Watch out for default values (use
withDefaults) - In functions like
watch(), wrap with a getter:() => propName - In templates, destructured props always work!
๐ก Pro Tips
Tip 1: Always Use TypeScript for Clarity
<script setup lang="ts">
interface Props {
count: number
message?: string
}
const { count, message = 'Hello' } = defineProps<Props>()
</script>
Tip 2: Computed for Transformations
<script setup>
import { computed } from 'vue'
const { price } = defineProps(['price'])
// โ
Perfect for derived values
const formattedPrice = computed(() => `${price.toFixed(2)}`)
</script>
You did it! ๐ Now you understand how props destructuring works in Vue.js. Remember: the gift box is always connected to your shelf in Vue 3.5+, but be careful when passing values to functions!
