From my notes

Vue components in depth

Questions and flashcards from your notes on the Vue docs' Components In-Depth chapter — compiler macros, prop naming and read-only props, local drafts of props, event arguments, several v-models, v-model modifiers, defineModel and its pre-3.4 equivalent, fallthrough attributes, slots and dynamic scoped slots, provide/inject per subtree and async components — with a fact check of the notes.

Written from your two Components In-Depth notes: props, events and v-model and slots, provide/inject, fallthrough attributes and async components. The matching study pages are Components: props, events and v-model and Components: attrs, slots and provide.

Know

  • Props: macros versus imports, prop name casing, which mutations warn, a local draft that resets when the prop changes.
  • Events and v-model: listener arguments, several named models, .number falling back to the string, defineModel without a parent binding, and the computed-based pattern it replaced.
  • Attributes and slots: fallthrough through nested components, inheritAttrs: false and what $attrs contains, slot shorthands, a data table with dynamic scoped slots, conditional slots.
  • Provide/inject and async components: per-subtree state, injection defaults, app-level provide, and the loader function defineAsyncComponent expects.

Fact check of your notes

You fixed the provide object syntax and the required-props rule since the last check. These are still in the notes.

Gotcha· Global registration happens on the app instance

"Global registration in app.vue" should be app.component('Name', Component) on the application instance in main.ts; App.vue is a component and cannot register globally.

Gotcha· The argument comes before the modifiers in v-model

v-model.capitalize:name should be v-model:name.capitalize, and name.toUpperCase() changes nothing because the result is discarded; the transformation belongs in the set option of defineModel.

Gotcha· The event names in the example do not match

The example declares updatedName but emits updateName, and listens with @updated-number for updateNumber. Listeners must match the declared name; only camelCase to kebab-case is converted.

Gotcha· Scoped slots are not an emit substitute

Events tell the parent that something happened. Scoped slots hand the child's data to the parent's markup, so the parent decides how each item looks.

Gotcha· A composable can give each caller its own state

The new provide/inject note says a composable would make all three lists share one value. That is only true when the composable keeps its state at module level. A composable that creates state inside the function gives each caller a copy, but that copy cannot reach the caller's children without props or provide, which is why provide/inject is the right tool for per-subtree state.

Exercise

Exercise
  • Build the DataTable with cell-<key> scoped slots and override two columns from the parent.
  • Write one input component twice, once with defineModel and once with a prop, an emit and a writable computed, and check that both behave the same.
  • Render three lists that each provide their own state, and confirm that children of one list never see another list's state.

Be able to say

Be able to say· How does v-model work on a component?

"It is a prop plus an event: modelValue and update:modelValue by default, or a named pair such as title and update:title with v-model:title, so a component can have several. defineModel() declares both and returns a ref; writing it emits the update, and if no parent binds it, it behaves as local state. Before 3.4 you wrote the prop, the emit and a writable computed yourself. Modifiers arrive as a modifiers object, and transformations go in the set or get option."

Be able to say· How do fallthrough attributes work?

"Attributes and listeners the parent passes but the component does not declare as props or emits fall through to its single root element, with class and style merged. If that root is another component, they are passed on. With several roots nothing is applied until one binds $attrs. inheritAttrs: false turns this off so I can put v-bind="$attrs" on an inner element; in Vue 3 $attrs includes class, style and listeners."

Be able to say· When do you use provide/inject instead of a store?

"When the state belongs to one subtree rather than the whole app: a form and its fields, a tabs container and its panels, or several instances of the same list that each need their own shared state. Each provider creates its own state and descendants get the nearest one. A store is a singleton, so every instance would share it. I keep mutations in the provider and provide readonly() state plus functions."

Your notes

Open in Notes

Nothing yet. Notes filed here show up on this page and the section overview.