How does two-way binding (v-model) work?
1. What is v-model
v-model is a directive that binds a component variable's value
to a form element (input, textarea, select, etc.) in both directions:
- when the data changes → the UI updates
- when the user types into the form → the variable updates
In other words, v-model = "data ↔ UI".
2. Basic usage example
<template>
<input v-model="message" placeholder="Enter text" />
<p>You entered: {{ message }}</p>
</template>
<script setup>
import { ref } from 'vue'
const message = ref('')
</script>What happens:
- When the user types text →
message.valueupdates. - When
message.valuechanges → theinputautomatically shows the new value.
Vue creates two-way synchronization without you having to write handlers by hand.
3. How v-model works "under the hood"
Take this code:
<input v-model="message" />Vue translates it into plain attributes and events:
<input
:value="message"
@input="message = $event.target.value"
/>In other words:
:value- one-way data binding (from the component → to the DOM);@input- feedback (from the DOM → to the component).
That is how you get two-way data binding.
4. Working with different element types
| Element | What it binds | Example |
|---|---|---|
<input type="text"> | value ↔ text | <input v-model="text" /> |
<input type="checkbox"> | checked ↔ boolean | <input type="checkbox" v-model="isChecked" /> |
<input type="radio"> | checked ↔ value | <input type="radio" value="A" v-model="choice" /> |
<select> | value ↔ selected value | <select v-model="option"> |
<textarea> | value ↔ text | <textarea v-model="comment"></textarea> |
5. Two-way binding between components
v-model can be used not only with form elements,
but also to link a parent and a child component.
Parent:
<UserInput v-model="username" />Child component:
<template>
<input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
</template>
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>The parent passes a value through v-model → the modelValue prop
The child reports changes through the update:modelValue event
This is the standard
v-modelcontract in Vue 3: prop:modelValue→ emit:update:modelValue
6. Several v-models on one component
Vue 3 lets you use several independent v-models with names:
<MyInput v-model:title="pageTitle" v-model:content="pageText" />Child component:
<script setup>
defineProps(['title', 'content'])
defineEmits(['update:title', 'update:content'])
</script>7. v-model modifiers
Vue offers convenient modifiers that transform the data on input:
| Modifier | Description | Example |
|---|---|---|
.lazy | Updates the value only after change, not input | <input v-model.lazy="text" /> |
.trim | Automatically trims whitespace from the start and end | <input v-model.trim="name" /> |
.number | Converts the value to a number | <input v-model.number="age" /> |
8. Under the hood of reactivity
When you write v-model="x":
- Vue tracks that the DOM element depends on
x; - when
xchanges, thevalueattribute updates; - on an
input/changeevent, Vue triggers a reverse update →x = $event.target.value.
These two directions form a reactive loop, keeping the UI and the state instantly in sync.
Summary
v-modelis the mechanism for two-way data binding in Vue.js.It automatically synchronizes the component's state and the UI:
- from code → to the DOM (
:value="...")- from the DOM → to code (
@input="...")It works both with form elements and with components, and supports modifiers and multiple models.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.