Props down events up
The golden rule: parents send data to children with props, and children talk back with events.
In this page:
Syntax
// parent passes data down, child sends events up
<child-name :prop-name="value" @event-name="handler"></child-name>
Props down events up
This one-way data flow keeps applications predictable: state lives in one owner and changes are requested through events. A child should never mutate a prop; instead it emits an event and the parent decides how to update its own state.
Note:
If a child needs a modifiable copy, copy the prop into local data.
Example: Props down events up
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<p>Cart total: {{ total }}</p>
<product-row v-for="p in products" :key="p.id" :product="p" @buy="total += $event"></product-row>
</div>
<script>
const app = Vue.createApp({
data() { return { total: 0, products: [{ id: 1, name: "Pen", price: 3 }, { id: 2, name: "Book", price: 12 }] }; },
});
app.component("product-row", {
props: ["product"],
emits: ["buy"],
template: '<div>{{ product.name }} ${{ product.price }} <button @click="$emit(\'buy\', product.price)">Buy</button></div>',
});
app.mount("#app");
document.querySelectorAll("button")[1].click();
document.querySelectorAll("button")[1].click();
Vue.nextTick(() => console.log(document.querySelector("p").textContent));
</script>
</body>
</html>
<!-- Output:
Rendered: Cart total: 24Pen $3 BuyBook $12 Buy
console: Cart total: 24
-->
Live Example
Related Topics
Common Mistakes
- Mutating a prop in the child
- Sharing state through globals
- Two-way binding everywhere
Chapter Summary
- Props flow down
- Events flow up
- The owner updates the state
- Never mutate props
🔒
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: