Under The Hood
frontend vue Vue 3.4+

defineModel() Macro: Synthetic Props and Update Events

Last updated
Prerequisites:
Vue v-model basics
script-setup compiler macros
  • vue
  • defineModel
  • v-model
  • two-way-binding
  • macros
  • script-setup

Read at your depth

The practical view

`defineModel()` is a compiler macro in `<script setup>` that simplifies two-way bindings. `const model = defineModel();` replaces the boilerplate of declaring `defineProps(['modelValue'])` and `defineEmits(['update:modelValue'])`. You can mutate `model.value = 'newVal'` directly in the child, and Vue automatically emits the update event to synchronize the parent's `v-model`.

The same idea in other frameworks

react equivalent
Controlled props pattern: passing `value` and `onChange` callbacks.

Legacy vs modern

Manual props/emits v-model Boilerplate vs defineModel()

Manual `v-model` requires declaring matching props and emits; `defineModel()` creates a clean, mutable ref.

before → after
Manual Props & Emits (Vue 3.2)
const props = defineProps(['modelValue']); const emit = defineEmits(['update:modelValue']); // ❌ Verbose
Vue 3.4+ defineModel()
const model = defineModel({ type: String, default: '' }); // ✅ NEW: Direct mutable ref

Interview gotchas

Context

Interviewers test your knowledge of advanced `v-model` features in Vue 3.4+.

The mechanical answer

For named models (e.g. `v-model:title="postTitle"`), pass the name as the first argument: `const title = defineModel('title')`. For custom modifiers (e.g. `v-model.capitalize="text"`), destructure the returned tuple: `const [model, modifiers] = defineModel({ set(value) { if (modifiers.capitalize) return value.toUpperCase(); return value; } })`.

Trap

Do not declare `defineProps(['title'])` and `defineModel('title')` in the same component; declaring both creates conflicting duplicate prop declarations.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.