Работа с формами
При работе с формами часто требуется синхронизировать состояния элементов ввода в форме с соответствующим состоянием в JavaScript. Добавлять вручную привязки значений и обработчики событий изменения может быть обременительно:
template
<input
:value="text"
@input="event => text = event.target.value"
>
Директива v-model
помогает упростить указанное выше до:
template
<input v-model="text">
Кроме того, v-model
может быть использована на полях различных типов, элементах <textarea>
и <select>
. Она автоматически разворачивается на различные пары свойств и событий DOM в зависимости от элемента на котором используется:
- Элементы
<input>
с текстовым типом и<textarea>
используют свойствоvalue
и событиеinput
; - Элементы
<input type="checkbox">
и<input type="radio">
используют свойствоchecked
и событиеchange
; - Элементы
<select>
используют свойствоvalue
и событиеchange
.
Примечание
Директива v-model
игнорирует начальное значение атрибутов value
, checked
или selected
на любых элементах форм. Источником истины всегда считается текущее состояние JavaScript. Начальное значение нужно объявить на стороне JavaScript, используя API реактивности.
Обычное использование
Текст
template
<p>Сообщение: {{ message }}</p>
<input v-model="message" placeholder="отредактируй меня" />
Сообщение:
Примечание
Для языков, которые требуют IME (китайский, японский, корейский и т.д.), можно заметить, что v-model
не обновляется во время IME-композиции. Если необходимо обрабатывать и эти обновления, используйте слушатель события input
и привязку к value
вместо использования v-model
.
Многострочный текст
template
<span>Многострочное сообщение:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<textarea v-model="message" placeholder="введите несколько строчек"></textarea>
Многострочное сообщение:
Внутри <textarea>
ИНТЕРПОЛЯЦИЯ НЕ РАБОТАЕТ, используйте v-model
.
template
<!-- НЕ БУДЕТ РАБОТАТЬ -->
<textarea>{{ text }}</textarea>
<!-- А так работает -->
<textarea v-model="text"></textarea>
Чекбоксы
Один чекбокс, привязанный к булевому значению:
template
<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>
Список чекбоксов, привязанных к массиву или значениям Set:
js
const checkedNames = ref([])
template
<div>Отмеченные имена: {{ checkedNames }}</div>
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames" />
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames" />
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames" />
<label for="mike">Mike</label>
Отмеченные имена: []
В этом случае массив checkedNames
всегда будет содержать значения выбранных чекбоксов.
Радиокнопки
template
<div>Выбрано: {{ picked }}</div>
<input type="radio" id="one" value="Один" v-model="picked" />
<label for="one">Один</label>
<input type="radio" id="two" value="Два" v-model="picked" />
<label for="two">Два</label>
Выбрано:
Выпадающие списки
Выбор одного варианта из списка:
template
<div>Выбрано: {{ selected }}</div>
<select v-model="selected">
<option disabled value="">Выберите один из вариантов</option>
<option>А</option>
<option>Б</option>
<option>В</option>
</select>
Выбрано:
Примечание
Если начальное значение выражения v-model
не соответствует ни одному из вариантов списка, элемент <select>
будет отображаться в «невыбранном» состоянии. В iOS это приведёт к тому, что пользователь не сможет выбрать первый элемент, потому что iOS не сгенерирует событие change
в этом случае. Поэтому рекомендуется добавлять отключённый disabled
-вариант выбора с пустым значением value, как показано в примере выше.
Выбор нескольких вариантов из списка (с привязкой к массиву):
template
<div>Выбраны: {{ selected }}</div>
<select v-model="selected" multiple>
<option>А</option>
<option>Б</option>
<option>В</option>
</select>
Выбраны: []
Динамическое отображение списка опций с помощью v-for
:
js
const selected = ref('A')
const options = ref([
{ text: 'Один', value: 'A' },
{ text: 'Два', value: 'B' },
{ text: 'Три', value: 'C' }
])
template
<select v-model="selected">
<option v-for="option in options" :value="option.value">
{{ option.text }}
</option>
</select>
<div>Выбрано: {{ selected }}</div>
Привязка значений
Для радиокнопок и выпадающих списков в качестве привязываемых значений v-model
обычно будут статические строки (или булевые значения для чекбокса):
template
<!-- `picked` будет строкой "a" при выборе -->
<input type="radio" v-model="picked" value="a" />
<!-- `toggle` может принимать значение true или false -->
<input type="checkbox" v-model="toggle" />
<!-- `selected` будет строкой "abc" при выборе первого пункта -->
<select v-model="selected">
<option value="abc">ABC</option>
</select>
Но иногда может потребоваться привязать значение к динамическому свойству текущего активного экземпляра. Для этого можно использовать v-bind
. Кроме того, использование v-bind
позволяет привязать значение поля с нестроковыми значениями.
Чекбокс
template
<input
type="checkbox"
v-model="toggle"
true-value="да"
false-value="нет" />
Атрибуты true-value
и false-value
— специальные атрибуты Vue, которые работают только в связке с v-model
. Здесь значение свойства toggle
будет установлено в 'да'
, когда чекбокс выбран, и в 'нет'
когда сброшен. Также можно привязать их к динамическим значением с помощью v-bind
:
template
<input
type="checkbox"
v-model="toggle"
:true-value="dynamicTrueValue"
:false-value="dynamicFalseValue" />
Совет
Атрибуты true-value
и false-value
не влияют на атрибут value
элемента input
, потому что браузеры пропускают невыбранные чекбоксы при отправке форм. Чтобы гарантировать отправку одного из двух значений с формой (например, «да» или «нет») используйте радиокнопки.
Радиокнопки
template
<input type="radio" v-model="pick" :value="first" />
<input type="radio" v-model="pick" :value="second" />
Значение pick
будет установлено в first
при выборе первой радиокнопки, и в значение second
при выборе второй.
Выпадающие списки
template
<select v-model="selected">
<!-- инлайновый объект с данными -->
<option :value="{ number: 123 }">123</option>
</select>
Директива v-model
поддерживает привязку и нестроковых значений! В примере выше, когда опция выбрана, значение selected
будет объектом { number: 123 }
.
Модификаторы
.lazy
По умолчанию v-model
синхронизирует поле ввода с данными по событию input
(кроме вышеупомянутых исключений для композиции IME). Можно воспользоваться модификатором lazy
, чтобы синхронизация происходила по событию change
:
template
<!-- синхронизация после события "change" вместо "input" -->
<input v-model.lazy="msg" />
.number
Для автоматического приведения введённого пользователем к числу можно добавить модификатор number
:
template
<input v-model.number="age" />
Если значение не получится привести к числу с помощью parseFloat()
, то будет возвращено исходное значение. В частности, если поле ввода пустое (например, после того, как пользователь очистил поле ввода), возвращается пустая строка. Это поведение отличается от свойства DOM valueAsNumber
.
Модификатор number
автоматически применяется к полям type="number"
.
.trim
Если необходимо автоматически удалять пробельные символы в начале и в конце строки, можно добавить модификатор trim
:
template
<input v-model.trim="msg" />
Использование v-model
с компонентами
Если ещё не знакомы с компонентами Vue, пока просто пропустите эту секцию.
Встроенные в HTML элементы ввода не всегда соответствуют всем потребностям. К счастью, компоненты Vue позволяют создавать собственные аналоги с полностью настраиваемым поведением. Эти элементы могут работать с директивой v-model
! Подробнее в разделе использования компонентов вместе с v-model
.