Vue apps scale when data flows predictably: props down, events up, and provide/inject for deep trees. Avoid ad-hoc global singletons until a real store (Pinia) is justified.
Props and emits
Parent passes data with props; child notifies parent with emit('eventName', payload). Keep events named like user intentions: update:modelValue, save, close.
Provide / inject
Ancestor provide('key', value); descendant inject('key'). Useful for theme, locale, or auth snapshot without drilling through layout shells.
When to reach for a store
When unrelated branches share mutable state, undo history, or server cache invalidation—Pinia (or similar) centralizes updates. Start with lifted state in the closest common parent.
Self-check
- What is the first fix for prop drilling through a layout that does not use the prop?
- How does provide/inject differ from props?
Challenge
Filter bar emits up
- Type in the filter input and watch the parent list narrow.
- Confirm the child never owns the full list—only emits the query.
Done when: parent list filters when the child emits the search string.