Vue interview

Component communication

Props, events, v-model, provide/inject, stores, slots, template refs and fallthrough attributes — when to use which, one-way data flow, defineModel with modifiers, scoped slots, and attributes with several root elements.

From your Props, Events, V-Model and Slots, Provide/inject, Fallthrough attrs notes.

Know

  • Options: props down, events up, v-model for both, provide/inject for a subtree, a store or shared composable for app-wide state, slots for content, template refs with defineExpose for imperative calls, $attrs for undeclared attributes. Use the most local one that works.
  • One-way data flow: don't change props; computed for a transformed value, a ref copy for a draft, an event or defineModel to change the parent's value.
  • v-model: modelValue plus update:modelValue; defineModel() (3.4), named models with an argument, modifiers through const [model, modifiers] = defineModel({ set }).
  • Provide/inject: scoped to the providing instance; provide readonly state plus update functions, use an InjectionKey, wrap in provideX/useX.
  • Slots: named slots and fallback content; scoped slots pass child data to the parent's template; $slots for conditional wrappers.
  • Attributes: fall through to a single root; with several roots nothing is applied and Vue warns; inheritAttrs: false plus v-bind="$attrs" to choose the element.

Fact check of your notes

Gotcha· The argument comes before the modifier

<MyComp v-model.capitalize:name="…"> should be v-model:name.capitalize. And if (nameModifiers.capitalize) name.toUpperCase() changes nothing, because name is a ref and strings are immutable; transform the value in the set option of defineModel('name', { set: v => … }).

Gotcha· Scoped slots send data, not events

Scoped slots don't send information to the parent the way an emit does. They let the child pass data into the slot content the parent provides, at render time, so the parent decides how each item looks while the child owns the logic.

Gotcha· Global components are registered in the entry file

"Global registration in app.vue": global components are registered with app.component() where the app is created, usually main.ts.

Exercise

Exercise
  • Build a <DataList :items> with a scoped #item slot, and use it on two pages that render rows differently.
  • Build a text input component with defineModel and a custom .capitalize modifier, and a two-root component that forwards class with $attrs.

Be able to say

Be able to say· How do components talk to each other in Vue?

"Props down and events up, with v-model when one value goes both ways. When something has to skip levels inside one part of the tree, provide and inject. When unrelated parts of the app share state, a store like Pinia. Slots for passing content, scoped slots when the child supplies the data. Template refs only for imperative calls like open(). I pick the most local option that works."

Your notes

Open in Notes

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