Props — Data Flowing Down
BookCard still shows "Dune" every time, because the title is written inside it. A card that can only show one book is useless. The list knows which books exist; the card should just display whatever book it is given. Props are how a parent hands data to a child.
The rule
Props flow down, and the child only reads them.
The child declares which props it accepts with defineProps. It is a compiler macro, so there is nothing to import:
<!-- BookCard.vue -->
<script setup>
const props = defineProps({
id: { type: Number, required: true },
title: { type: String, required: true },
pages: Number,
read: { type: Boolean, default: false }
})
</script>
<template>
<article class="card">
<h3>{{ title }}</h3>
<p>{{ pages }} pages</p>
</article>
</template>The parent passes values as attributes:
<BookCard :id="1" title="Dune" :pages="412" :read="true" />Look closely at the colons. title="Dune" passes the literal string Dune. :pages="412" means "evaluate 412 as JavaScript", so the child receives the number 412, not the text "412". Without the colon, pages="412" would pass a string and fail the Number type check with a warning. Any time a prop is not a fixed string, use the colon: :title="book.title".
In the template, props are used by name ({{ title }}). In script code, read them through the object: props.title.
One-way data flow: when the parent's value changes, the new value flows down into the child. But the child must never assign to a prop. props.pages = 0 triggers a warning and the parent's data does not change. The parent owns the data; the child borrows it. (How a child asks the parent for a change is the next lesson.)
The shortcut
For every value in a child, ask "who owns this?" If the parent decides it, it is a prop. Then check the colon: fixed string, no colon; anything else, colon.
Who owns the book?
The
booksarray lives in the parent, so each card receives its book through props.
A naming note: declare props in camelCase (pageCount) and you may pass them as page-count="..." in templates; Vue matches the two.
Drills
Answer fast — trust the rule.
What does BookCard receive for pages when the parent writes pages="412" with no colon?
BookCard runs props.title = 'Untitled'. What happens?
Which declaration makes title a required string prop?
The parent's book.pages changes from 412 to 420. What happens in BookCard?
Remember
definePropsdeclares what a child accepts; the parent passes values as attributes.- Shortcut: "who owns it?" Parent means prop. Non-string value means colon.
- Trap: assigning to a prop inside the child. Read it; do not write it.
