Как работает двусторонняя привязка в 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: ''
}
}

Здесь происходит следующее:

  1. Значение message устанавливается как value поля <input>.

  2. Когда пользователь что-то вводит, Vue ловит input-событие и обновляет message.

  3. Когда message меняется в коде — значение поля ввода обновляется.

Как это работает под капотом

Vue реализует v-model через сочетание следующих вещей:

1. Односторонняя привязка :value

&lt;input :value="message"&gt;

Устанавливает начальное значение поля из модели.

2. Обработка события @input

&lt;input :value="message" @input="message = $event.target.value"&gt;

Позволяет обновить модель при изменении значения пользователем.

Объединённый синтаксис — v-model:

&lt;input v-model="message"&gt;

Vue сам автоматически подставляет :value и @input.

Реактивность в Vue

Vue отслеживает изменения через реактивную систему. Когда значение свойства, связанного через v-model, изменяется:

  • Vue уведомляет виртуальный DOM.

  • Происходит повторный рендер DOM-узлов, использующих это значение.

  • Всё это происходит прозрачно и эффективно, без необходимости вручную обновлять DOM.

Примеры для разных типов данных

Строка (text input)

&lt;input v-model="username"&gt;
data() {
return {
username: ''
}
}

Многострочный текст (textarea)

&lt;textarea v-model="comment"&gt;&lt;/textarea&gt;

Чекбокс

&lt;input type="checkbox" v-model="isChecked"&gt;
data() {
return {
isChecked: false
}
}

Если isChecked = true, чекбокс будет отмечен.

Радиокнопки

&lt;input type="radio" v-model="picked" value="One"&gt;
&lt;input type="radio" v-model="picked" value="Two"&gt;
data() {
return {
picked: ''
}
}

Селект (одиночный выбор)

&lt;select v-model="selected"&gt;
&lt;option disabled value=""&gt;Выбери опцию&lt;/option&gt;
&lt;option&gt;Один&lt;/option&gt;
&lt;option&gt;Два&lt;/option&gt;
&lt;/select&gt;
data() {
return {
selected: ''
}
}

Селект (множественный выбор)

&lt;select v-model="selectedOptions" multiple&gt;
&lt;option&gt;HTML&lt;/option&gt;
&lt;option&gt;CSS&lt;/option&gt;
&lt;option&gt;JavaScript&lt;/option&gt;
&lt;/select&gt;
data() {
return {
selectedOptions: \[\]
}
}

Модификаторы v-model

Vue предоставляет специальные модификаторы для тонкой настройки поведения привязки:

.lazy

Значение обновляется не при input, а при событии change (например, при потере фокуса):

&lt;input v-model.lazy="name"&gt;

.number

Автоматически преобразует ввод в число:

&lt;input v-model.number="age"&gt;

Строка "42" превратится в число 42.

.trim

Удаляет пробелы в начале и конце:

&lt;input v-model.trim="username"&gt;

v-model с компонентами

Vue позволяет использовать v-model и для пользовательских компонентов, а не только для HTML-элементов.

Для этого компонент должен:

  1. Принимать modelValue как prop.

  2. Эмитить update:modelValue при изменении.

Пример:

&lt;!-- Родитель --&gt;
&lt;MyInput v-model="form.email" /&gt;
&lt;!-- Компонент MyInput.vue --&gt;
&lt;template&gt;
&lt;input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)"&gt;
&lt;/template&gt;
&lt;script&gt;
export default {
props: \['modelValue'\]
}
&lt;/script&gt;

Таким образом, можно реализовать кастомные поля, селекты, автокомплиты и другие элементы с поддержкой двухсторонней привязки.

Особенности

  1. Реактивность сохраняется — все изменения отслеживаются Vue.

  2. Привязка работает синхронно с интерфейсом.

  3. Изменения можно обрабатывать вручную через watchers или computed.

  4. Можно комбинировать 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.