Как работает двусторонняя привязка в Vue?
Во Vue.js двусторонняя привязка (two-way binding) позволяет автоматически синхронизировать данные между моделью (JavaScript-объектом) и пользовательским интерфейсом (DOM). Это значит, что если пользователь меняет значение в input-поле, то обновляется соответствующее свойство в data, и наоборот — при изменении значения в коде оно автоматически отражается в интерфейсе.
Основной механизм — v-model
Vue предоставляет директиву v-model, которая реализует двустороннюю привязку для формовых элементов (input, textarea, select, checkbox и т.д.).
Простой пример:
<input v-model="message" type="text">
<p>{{ message }}</p>
В data:
data() {
return {
message: ''
}
}
Здесь происходит следующее:
-
Значение message устанавливается как value поля <input>.
-
Когда пользователь что-то вводит, Vue ловит input-событие и обновляет message.
-
Когда message меняется в коде — значение поля ввода обновляется.
Как это работает под капотом
Vue реализует v-model через сочетание следующих вещей:
1. Односторонняя привязка :value
<input :value="message">
Устанавливает начальное значение поля из модели.
2. Обработка события @input
<input :value="message" @input="message = $event.target.value">
Позволяет обновить модель при изменении значения пользователем.
Объединённый синтаксис — v-model:
<input v-model="message">
Vue сам автоматически подставляет :value и @input.
Реактивность в Vue
Vue отслеживает изменения через реактивную систему. Когда значение свойства, связанного через v-model, изменяется:
-
Vue уведомляет виртуальный DOM.
-
Происходит повторный рендер DOM-узлов, использующих это значение.
-
Всё это происходит прозрачно и эффективно, без необходимости вручную обновлять DOM.
Примеры для разных типов данных
Строка (text input)
<input v-model="username">
data() {
return {
username: ''
}
}
Многострочный текст (textarea)
<textarea v-model="comment"></textarea>
Чекбокс
<input type="checkbox" v-model="isChecked">
data() {
return {
isChecked: false
}
}
Если isChecked = true, чекбокс будет отмечен.
Радиокнопки
<input type="radio" v-model="picked" value="One">
<input type="radio" v-model="picked" value="Two">
data() {
return {
picked: ''
}
}
Селект (одиночный выбор)
<select v-model="selected">
<option disabled value="">Выбери опцию</option>
<option>Один</option>
<option>Два</option>
</select>
data() {
return {
selected: ''
}
}
Селект (множественный выбор)
<select v-model="selectedOptions" multiple>
<option>HTML</option>
<option>CSS</option>
<option>JavaScript</option>
</select>
data() {
return {
selectedOptions: \[\]
}
}
Модификаторы v-model
Vue предоставляет специальные модификаторы для тонкой настройки поведения привязки:
.lazy
Значение обновляется не при input, а при событии change (например, при потере фокуса):
<input v-model.lazy="name">
.number
Автоматически преобразует ввод в число:
<input v-model.number="age">
Строка "42" превратится в число 42.
.trim
Удаляет пробелы в начале и конце:
<input v-model.trim="username">
v-model с компонентами
Vue позволяет использовать v-model и для пользовательских компонентов, а не только для HTML-элементов.
Для этого компонент должен:
-
Принимать modelValue как prop.
-
Эмитить update:modelValue при изменении.
Пример:
<!-- Родитель -->
<MyInput v-model="form.email" />
<!-- Компонент MyInput.vue -->
<template>
<input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)">
</template>
<script>
export default {
props: \['modelValue'\]
}
</script>
Таким образом, можно реализовать кастомные поля, селекты, автокомплиты и другие элементы с поддержкой двухсторонней привязки.
Особенности
-
Реактивность сохраняется — все изменения отслеживаются Vue.
-
Привязка работает синхронно с интерфейсом.
-
Изменения можно обрабатывать вручную через watchers или computed.
-
Можно комбинировать v-model с другими директивами — v-if, v-bind, v-show, v-for и т.д.
v-model в Vue 3 (нововведения)
С Vue 3 механизм v-model расширился:
-
Можно иметь несколько моделей (много v-model в одном компоненте).
-
Каждый v-model имеет своё имя.
Пример:
<MyComponent
v-model:title="pageTitle"
v-model:content="pageContent"
/>
В компоненте:
props: \['title', 'content'\],
emits: \['update:title', 'update:content'\]
Теперь компонент может управлять разными частями данных независимо.
Vue реализует двустороннюю привязку с высокой степенью гибкости, обеспечивая простой синтаксис (v-model) и мощную внутреннюю реактивную систему. Этот подход позволяет быстро и просто создавать формы, интерфейсы редактирования и интерактивные элементы без необходимости вручную отслеживать и синхронизировать данные между DOM и JavaScript.