tezvyn:

How do you structure components and state for a dynamic Vue form?

AI-drafted, machine-checkedSource: vuejs.orgadvanced

This tests your design of normalized reactive state for dynamic Vue forms. A great answer uses a flat item array with stable keys, row components or scoped slots, and schema-driven validation. Red flags include mutating by index or using array indices as keys.

WHAT THIS TESTS: This question evaluates whether you can manage reactive collections in Vue without breaking reactivity or performance. The interviewer cares about your mental model of array change detection, key-driven reconciliation, component boundary design, and how validation scales when the field count is unknown at compile time.

A GOOD ANSWER COVERS: First, keep the data model as a flat reactive array of objects where each object represents one row and carries its own identity, typically via an id field. Second, render the list with v-for and bind a stable unique value to the key attribute, never the array index, so Vue can track insertions and deletions without destroying internal state. Third, extract each row into its own component or use a scoped slot so that mutations, emits, and local UI state stay encapsulated rather than leaking into the parent. Fourth, treat validation as a cross-cutting concern: define a schema or composable that accepts the dynamic array and returns errors per row, keeping validation metadata out of the business data model.

COMMON WRONG ANSWERS: Directly mutating the array by index, such as items[i] = newValue, because Vue cannot detect this change on arrays without using splice or reactive helpers. Using the loop index as the key, which causes focus loss, stale component state, and incorrect validation bindings when rows are reordered or removed. Burying validation rules inside each data object, which couples schema to state and makes server serialization messy. Creating deeply nested reactive objects unnecessarily, which increases overhead for large forms.

LIKELY FOLLOW-UPS: How would you handle asynchronous validation for a single row without blocking the rest of the form? What strategy would you use to preserve form state if the user navigates away and returns? How do you optimize rendering when the list grows past one hundred rows?

ONE CONCRETE EXAMPLE: Imagine a work experience form where each entry has company, role, and dates. You store experiences as ref([{ id: 'a1', company: '', role: '', start: '', end: '' }]). The parent iterates with v-for="exp in experiences" :key="exp.id". Each row is a WorkExperienceRow component that receives the object via v-model or a defined prop and emits update events. A useDynamicForm composable maintains the array and exposes addRow, removeRowById, and validateAll functions. Validation rules live in a separate schema object keyed by field name, and the composable maps errors to rows by id rather than by index.

Read the original → vuejs.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.