Chapter 62: Vue $props Object

The $props object (also written as this.$props in Options API or simply props in modern Composition API)

This object is the official, single source of truth for all data that the parent component deliberately passed down to this child component.

Understanding $props deeply is what separates people who write fragile, hard-to-maintain Vue code from people who write clean, scalable, type-safe, production-ready Vue code.

1. What exactly is $props? (Very clear mental model)

When a parent uses your component like this:

vue

Vue does the following automatic splitting inside the child component:

  • Anything that matches a declared prop (name, type, required, default, validator) → goes into $props
  • Everything else → goes into $attrs (class, style, data-, aria-, unknown attributes, event listeners)

So in the child:

  • $props contains only:
    • user
    • isAdmin
    • loading
  • $attrs contains:
    • class
    • data-testid
    • @update listener

Important mental model:

$props = the contract between parent and child → Parent promises: “I will give you these exact named values” → Child promises: “I will use them only for reading (not writing)”

2. Modern Vue 3 – How You Actually Work with Props (2026 Standard)

In <script setup> (the way almost everyone writes Vue in 2026), you never write this.$props or even $props.

Instead you use:

vue

Or even shorter (very common):

vue

→ In template: {{ user.name }} (no props. prefix needed)

3. Real, Complete Example – UserProfile Component

Child: UserProfile.vue

vue

Parent – passing props

vue

4. Important Rules & Behaviors (2026 Must-Know)

Rule / Gotcha Behavior / Best Practice
Props are read-only Never do props.user.name = ‘new’ → Vue warns / throws in dev mode
Props are reactive If parent changes :user=”newUser” → child auto-updates
Optional props Use ? in type → isAdmin?: boolean → can be undefined
Default values defineProps<{ count?: number }>() const count = props.count ?? 0
Prop validation (rare in 2026) TypeScript + defineProps usually enough — old validator still works in Options API
Non-prop attributes Go to $attrs (class, style, data-, aria-, @events, unknown props)
v-model support Emit ‘update:modelValue’ → enables <MyComp v-model=”value” />
TypeScript + defineProps Best DX — autocompletion, type checking, required props

5. Quick Summary Table – Props vs $attrs (2026 Cheat Sheet)

Question $props (or just props) $attrs
What does it contain? Only declared props Everything else (class, style, events, unknown attrs)
Auto-applied to root? No — you use them manually Yes (unless inheritAttrs: false)
Can child modify? No — read-only Yes (but usually forward them)
Contains event listeners? No Yes
Type-safe? Yes — with defineProps<…> Partial (Record<string, any>)
Used for? Component configuration Forwarding to native elements / child components

Pro Tips from Real Projects (Hyderabad 2026)

  • Always use TypeScript + defineProps — catches 90% of prop-related bugs at compile time
  • Prefer kebab-case in templates (user-name) → auto-converted to camelCase (userName) in JS
  • Never mutate props — if child needs to change data → emit → parent updates
  • For very large prop lists → consider slots, provide/inject, or composables instead
  • Use default values and optional props wisely — makes component more reusable

Your mini practice task:

  1. Create UserCard.vue with props: user (object), isPremium?, size: ‘small’ | ‘large’
  2. Add conditional class based on isPremium and size
  3. Use it from parent with different users & sizes
  4. Try passing an undeclared prop (e.g. data-test) → check DevTools → it goes to $attrs

Any part confusing? Want full examples for:

  • v-model on custom component using props + emit?
  • Props validation with custom validator (old style)?
  • $props vs $attrs vs $emit full comparison?
  • Real UI library component with typed props + forwarded attrs?

Just tell me — we’ll build the next clean, type-safe component together 🚀

Happy propping from Hyderabad! 💙

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *