Привязка элементов формы
При работе с формами на фронтенде нам часто требуется синхронизировать состояние элементов ввода формы с соответствующим состоянием в 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, используя Reactivity API.
Основы
Текст (input type="text"
)
template
<p>Сообщение: {{ message }}</p>
<input v-model="message" placeholder="измени меня" />
Сообщение:
Примечание
Для языков, требующих IME (китайский, японский, корейский и т. д.), вы заметите, что v-model
не обновляется во время составления IME. Если вы хотите реагировать и на эти обновления, используйте свой собственный слушатель событий input
и привязку value
вместо использования v-model
.
Многострочный текст (textarea
)
template
<span>Многострочное сообщение:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<textarea v-model="message" placeholder="добавь несколько строк"></textarea>
Многострочное сообщение:
Обратите внимание, что интерполяция внутри <textarea>
не будет работать. Вместо этого используйте v-model
.
template
<!-- bad -->
<textarea>{{ text }}</textarea>
<!-- good -->
<textarea v-model="text"></textarea>
Флажок (input type="checkbox"
)
Одиночный флажок, булево значение:
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="Женя" v-model="checkedNames" />
<label for="jack">Женя</label>
<input type="checkbox" id="john" value="Ваня" v-model="checkedNames" />
<label for="john">Ваня</label>
<input type="checkbox" id="mike" value="Миша" v-model="checkedNames" />
<label for="mike">Миша</label>
Отмеченные имена: []
В этом случае массив checkedNames
всегда будет содержать значения из текущих отмеченных флажков.
Переключатель (input type="radio"
)
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">TДва/label>
Выбрано:
Выпадающий список (select
)
Выбор одного значения:
template
<div>Выбрано: {{ selected }}</div>
<select v-model="selected">
<option disabled value="">Выберите что-нибудь</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
Выбрано:
Примечание
Если начальное значение выражения v-model
не соответствует ни одному из вариантов, элемент <select>
будет отображаться в виде unselected. На iOS это приведет к тому, что пользователь не сможет выбрать первый элемент, потому что iOS не запускает событие изменения в этом случае. Поэтому рекомендуется предоставлять опцию disabled с пустым значением, как показано в примере выше.
Множественный выбор (привязка к массиву):
template
<div>Выбрано: {{ selected }}</div>
<select v-model="selected" multiple>
<option>A</option>
<option>B</option>
<option>C</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>
Привязка значения
Для элементов radio, checkbox и select значения привязки v-model
обычно являются статическими строками (или булевыми значениями для checkbox):
template
<!-- `picked` это строка "a" при выборе -->
<input type="radio" v-model="picked" value="a" />
<!-- `toggle` является либо истинным, либо ложным -->
<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="yes"
false-value="no" />
true-value
и false-value
— специфические для Vue атрибуты, которые работают только с v-model
. Здесь значение свойства toggle
будет установлено в 'yes'
, когда флажок установлен, и в 'no'
, когда флажок снят. Вы также можете привязать их к динамическим значениям с помощью v-bind
:
template
<input
type="checkbox"
v-model="toggle"
:true-value="dynamicTrueValue"
:false-value="dynamicFalseValue" />
Совет
Атрибуты true-value
и false-value
не влияют на атрибут value
элемента ввода, потому что браузеры не включают в формы не отмеченные флажки. Чтобы гарантировать, что в форме будет представлено одно из двух значений (например, «yes» или «no»), используйте вместо флажков переключатели.
Переключатель
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
к атрибуту v-model
:
template
<input v-model.number="age" />
Если значение не может быть разобрано с помощью parseFloat()
, то вместо него используется исходное (строковое) значение. В частности, если поле ввода пустое (например, после того, как пользователь его очистил), возвращается пустая строка. Это поведение отличается от DOM-свойства valueAsNumber
.
Модификатор number
применяется автоматически, если входные данные имеют type="number"
.
.trim
Если вы хотите, чтобы пробельные символы из пользовательского ввода обрезались автоматически, вы можете добавить модификатор trim
к атрибуту v-model
:
template
<input v-model.trim="msg" />
v-model
с компонентами
Если вы ещё не знакомы с компонентами Vue, можете пока пропустить этот пункт.
Встроенные типы ввода HTML не всегда могут удовлетворить ваши потребности. К счастью, компоненты Vue позволяют создавать многоразовые элементы ввода с полностью настраиваемым поведением. Эти элементы ввода также работают с v-model
! Чтобы узнать больше, прочитайте про использование v-model
в руководстве по компонентам.