# Работа с формами

# Типичное использование

Можно использовать директиву v-model для двунаправленного связывания данных с элементами форм input, textarea и select. Способ обновления элемента выбирается автоматически в зависимости от типа элемента. Хотя v-model и выглядит как нечто волшебное, в действительности это лишь синтаксический сахар для обновления данных в элементах ввода, с некоторыми поправками для исключительных случаев.

Совет

v-model игнорирует начальное значение атрибутов value, checked или selected на любых элементах форм. Данные текущего активного экземпляра всегда считаются источником истины. Начальное значение необходимо объявить на стороне JavaScript, внутри опции data компонента.

Внутренне v-model использует разные свойства и генерирует разные события для различных элементов ввода:

  • элементы для ввода текста и многострочного текста используют свойство value и событие input;
  • чекбоксы и радиокнопки используют свойство checked и событие change;
  • выпадающие списки используют свойство value и событие change.

Примечание

В языках, требующих IME (opens new window) (китайский, японский, корейский и т.д.), можно заметить, что v-model не обновляется по мере IME-композиции. Если необходимо обрабатывать и эти обновления, используйте обработчик события input и привязку к value вместо использования v-model.

# Текст

<input v-model="message" placeholder="отредактируй меня" />
<p>Введённое сообщение: {{ message }}</p>
1
2

See the Pen Handling forms: basic v-model by Vue (@Vue) on CodePen.

# Многострочный текст

<span>Введённое многострочное сообщение:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br />
<textarea v-model="message" placeholder="введите несколько строчек"></textarea>
1
2
3
4

See the Pen Handling forms: textarea by Vue (@Vue) on CodePen.

Интерполяция внутри textarea не будет работать. Используйте директиву v-model вместо неё.

<!-- плохо -->
<textarea>{{ text }}</textarea>

<!-- хорошо -->
<textarea v-model="text"></textarea>
1
2
3
4
5

# Чекбоксы

Один чекбокс, привязанный к булевому значению:

<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>
1
2

See the Pen Handling forms: checkbox by Vue (@Vue) on CodePen.

Список чекбоксов, привязанных к одному массиву:

<div id="v-model-multiple-checkboxes">
  <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>
  <br />
  <span>Отмеченные имена: {{ checkedNames }}</span>
</div>
1
2
3
4
5
6
7
8
9
10
Vue.createApp({
  data() {
    return {
      checkedNames: []
    }
  }
}).mount('#v-model-multiple-checkboxes')
1
2
3
4
5
6
7

See the Pen Handling forms: multiple checkboxes by Vue (@Vue) on CodePen.

# Радиокнопки

<div id="v-model-radiobutton">
  <input type="radio" id="one" value="Один" v-model="picked" />
  <label for="one">Один</label>
  <br />
  <input type="radio" id="two" value="Два" v-model="picked" />
  <label for="two">Два</label>
  <br />
  <span>Выбрано: {{ picked }}</span>
</div>
1
2
3
4
5
6
7
8
9
Vue.createApp({
  data() {
    return {
      picked: ''
    }
  }
}).mount('#v-model-radiobutton')
1
2
3
4
5
6
7

See the Pen Handling forms: radiobutton by Vue (@Vue) on CodePen.

# Выпадающие списки

Выбор одного варианта из списка:

<div id="v-model-select" class="demo">
  <select v-model="selected">
    <option disabled value="">Выберите один из вариантов</option>
    <option>А</option>
    <option>Б</option>
    <option>В</option>
  </select>
  <span>Выбрано: {{ selected }}</span>
</div>
1
2
3
4
5
6
7
8
9
Vue.createApp({
  data() {
    return {
      selected: ''
    }
  }
}).mount('#v-model-select')
1
2
3
4
5
6
7

See the Pen Handling forms: select by Vue (@Vue) on CodePen.

Примечание

Если начальное значение выражения v-model не соответствует ни одному из вариантов списка, элемент <select> будет отображаться в «невыбранном» состоянии. В iOS это приведёт к тому, что пользователь не сможет выбрать первый элемент, потому что iOS не сгенерирует событие change в этом случае. Поэтому рекомендуется предоставлять отключённый disabled-вариант выбора с пустым значением value, как показано в примере выше.

Выбор нескольких вариантов из списка (с привязкой к массиву):

<select v-model="selected" multiple>
  <option>А</option>
  <option>Б</option>
  <option>В</option>
</select>
<br />
<span>Выбрано: {{ selected }}</span>
1
2
3
4
5
6
7

See the Pen Handling forms: select bound to array by Vue (@Vue) on CodePen.

Динамическое отображение списка опций с помощью v-for:

<div id="v-model-select-dynamic" class="demo">
  <select v-model="selected">
    <option v-for="option in options" :value="option.value">
      {{ option.text }}
    </option>
  </select>
  <span>Выбрано: {{ selected }}</span>
</div>
1
2
3
4
5
6
7
8
Vue.createApp({
  data() {
    return {
      selected: 'A',
      options: [
        { text: 'Один', value: 'A' },
        { text: 'Два', value: 'B' },
        { text: 'Три', value: 'C' }
      ]
    }
  }
}).mount('#v-model-select-dynamic')
1
2
3
4
5
6
7
8
9
10
11
12

See the Pen Handling forms: select with dynamic options by Vue (@Vue) on CodePen.

# Связывание значений

Для радиокнопок и выпадающих списков в качестве v-model обычно используются статические строки (или булево для чекбокса):

<!-- `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>
1
2
3
4
5
6
7
8
9
10

Иногда необходимо связать значение с динамическим свойством текущего активного экземпляра. Для этого можно использовать v-bind. Кроме того, использование v-bind позволяет связывать поле ввода с нестроковыми значениями.

# Чекбокс

<input type="checkbox" v-model="toggle" true-value="да" false-value="нет" />
1
// если чекбокс выбран:
vm.toggle === 'да'
// если чекбокс сброшен:
vm.toggle === 'нет'
1
2
3
4

Совет

Атрибуты true-value и false-value не влияют на атрибут value тега input, потому что браузеры пропускают невыбранные чекбоксы при отправке форм. Чтобы гарантированно отправлять одно из двух значений с формой (например, «да» или «нет») используйте радиокнопки.

# Радиокнопки

<input type="radio" v-model="pick" :value="a" />
1
// если отмечено:
vm.pick === vm.a
1
2

# Списки выбора

<select v-model="selected">
  <!-- инлайновый объект с данными -->
  <option :value="{ number: 123 }">123</option>
</select>
1
2
3
4
// когда выбрано:
typeof vm.selected // => 'object'
vm.selected.number // => 123
1
2
3

# Модификаторы

# .lazy

По умолчанию v-model синхронизирует ввод с данными по событию input (за исключением вышеупомянутых событий IME). Можно указать модификатор lazy, чтобы использовать для синхронизации после события change:

<!-- синхронизируется по событию "change", а не "input" -->
<input v-model.lazy="msg" />
1
2

# .number

Для автоматического приведения введённого пользователем к Number, добавьте модификатор number:

<input v-model.number="age" type="number" />
1

Зачастую это полезно, потому что даже при указанном атрибуте type="number" значением поля ввода всегда будет строка. Если значение не удаётся распарсить с помощью parseFloat(), то возвращается оригинальное значение.

# .trim

Если необходимо, чтобы автоматически обрезались пробелы в начале и в конце строки, используйте модификатор trim для полей ввода, обрабатываемых через v-model:

<input v-model.trim="msg">
1

# Использование v-model с компонентами

Если вы ещё не знакомы с компонентами Vue, пока просто пропустите эту секцию

Встроенных в HTML элементов ввода не всегда достаточно. К счастью, компоненты Vue позволяют создавать собственные аналоги с полностью настраиваемым поведением. Эти элементы тоже могут работать с директивой v-model!

Подробнее в разделе пользовательские элементы ввода.

Deployed on Netlify.
Последнее обновление: 2021-01-23, 20:27:05 UTC