Skip to main content

How does the v-model directive work?

The v-model directive is a two-way data binding mechanism that connects the value of an input element (input, textarea, select, component) to a variable in Vue's state.

In simpler terms:

v-model binds data and the UI so that changing one automatically updates the other.


How does v-model work under the hood?

When you write:

html
<input v-model="message">

Vue turns this into two actions:

1. Binding the value (model → view)

html
:value="message"

The UI always shows the current data.

2. An event handler (view → model)

html
@input="message = $event.target.value"

When the user types text → the message variable updates.

It is combining these two directions that gives you two-way binding.


Example

vue
<template> <input v-model="name" /> <p>{{ name }}</p> </template> <script> export default { data() { return { name: '' } } } </script>

The user types text → name changes. name changes in code → the input updates.


How does v-model work on different form elements?

text input

html
<input v-model="text">

checkbox

html
<input type="checkbox" v-model="checked">

radio

html
<input type="radio" value="A" v-model="choice"> <input type="radio" value="B" v-model="choice">

select

html
<select v-model="selected"> <option value="1">One</option> </select>

checkbox with arrays

html
<input type="checkbox" value="A" v-model="items">

If checked → it is added to the array. If unchecked → it is removed.


v-model modifiers (Vue 3)

ModifierWhat it does
.lazyupdates the model on change, not input
.trimremoves whitespace from the edges
.numbercasts the value to a number

Example:

html
<input v-model.trim.number="age">

How does v-model work on components (Vue 3)

When you write:

html
<MyInput v-model="value" />

Vue replaces this with:

  • passing the modelValue prop
  • listening for the update:modelValue event

The component must look like this:

vue
<script> export default { props: ['modelValue'], emits: ['update:modelValue'] } </script> <template> <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" /> </template>

This is the internal mechanism of v-model.


Named models (Vue 3)

You can have several v-model bindings:

html
<DateRange v-model:start="startDate" v-model:end="endDate" />

The component must support:

  • a prop: start
  • an event: update:start
  • a prop: end
  • an event: update:end

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.