# Изменения в работе v-model
кардинальное изменение
# Обзор
Краткий обзор что изменилось:
- КАРДИНАЛЬНОЕ ИЗМЕНЕНИЕ: При использовании на компонентах
v-model
поменялись входной параметр и имя события:- входной параметр:
value
->modelValue
; - событие:
input
->update:modelValue
;
- входной параметр:
- КАРДИНАЛЬНОЕ ИЗМЕНЕНИЕ: Модификатор
.sync
дляv-bind
и опция компонентаmodel
были удалены и заменяются возможностью указать аргументv-model
; - НОВОЕ: Теперь возможны несколько привязок
v-model
на одном компоненте; - НОВОЕ: Добавлена возможность создавать собственные модификаторы для
v-model
.
Для получения дополнительной информации читайте дальше!
# Введение
Во Vue 2.0 директива v-model
требовала, чтобы использовался входной параметр value
. Для управления ещё другим входным параметром приходилось использовать v-bind.sync
. Кроме того, жёстко прописанная связь между v-model
и value
приводила к проблемам при обработке нативных и пользовательских элементов.
В версии 2.2 была добавлена опция компонента model
, которая позволила настраивать входной параметр и событие, используемые для v-model
. Но использовать можно было всё равно только одну v-model
на компоненте.
Во Vue 3 было унифицировано API для двусторонней привязки данных, чтобы уменьшить путаницу и предоставить разработчикам больше гибкости в работе с директивой v-model
.
# Синтаксис в 2.x
В версии 2.x использование v-model
на компоненте эквивалентно передаче входного параметра value
и отслеживании сгенерированного события input
:
<ChildComponent v-model="pageTitle" />
<!-- будет сокращённой версией для: -->
<ChildComponent :value="pageTitle" @input="pageTitle = $event" />
2
3
4
5
Если хочется изменить используемый входной параметр или имя события на другие, можно воспользоваться опцией model
в компоненте ChildComponent
:
<!-- ParentComponent.vue -->
<ChildComponent v-model="pageTitle" />
2
3
// ChildComponent.vue
export default {
model: {
prop: 'title',
event: 'change'
},
props: {
// это позволит использовать входной параметр `value` в других целях
value: String,
// теперь используем входной параметр `title` вместо `value`
title: {
type: String,
default: 'Заголовок по умолчанию'
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
В этом случае v-model
будет сокращённым вариантом для
<ChildComponent :title="pageTitle" @change="pageTitle = $event" />
# Использование v-bind.sync
В некоторых случаях может потребоваться «двусторонняя привязка» к входному параметру (иногда в дополнение к существующей v-model
для другого). Для этого рекомендуется генерировать событие по шаблону update:myPropName
. Например, для ChildComponent
из предыдущего примера с входным параметром title
можно передавать намерение о присвоении нового значения следующий образом:
this.$emit('update:title', newValue)
Тогда родительский компонент может прослушать это событие и обновить локальное свойство, если захочет. Например:
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
Для удобства, сокращённый вариант для этого шаблона с модификатором .sync
такой:
<ChildComponent :title.sync="pageTitle" />
# Синтаксис в 3.x
В версии 3.x v-model
на пользовательском компоненте эквивалентно передаче входного параметра modelValue
и отслеживании сгенерированного события update:modelValue
:
<ChildComponent v-model="pageTitle" />
<!-- будет сокращённой версия для: -->
<ChildComponent
:modelValue="pageTitle"
@update:modelValue="pageTitle = $event"
/>
2
3
4
5
6
7
8
# Аргументы v-model
Чтобы изменить имя свойства, вместо использования опции model
в компоненте, теперь можно передавать аргумент в директиву v-model
:
<ChildComponent v-model:title="pageTitle" />
<!-- будет сокращённой версией для: -->
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
2
3
4
5
Это также служит заменой модификатору .sync
и позволяет указать несколько v-model
на пользовательском компоненте.
<ChildComponent
v-model:title="pageTitle"
v-model:content="pageContent"
/>
<!-- будет сокращённой версией для: -->
<ChildComponent
:title="pageTitle"
@update:title="pageTitle = $event"
:content="pageContent"
@update:content="pageContent = $event"
/>
2
3
4
5
6
7
8
9
10
11
12
13
# Модификаторы v-model
Кроме жёстко заданных модификаторов v-model
в версии 2.x, таких как .trim
, в версии 3.x теперь поддерживается создание пользовательских модификаторов:
<ChildComponent v-model.capitalize="pageTitle" />
Подробнее о пользовательских модификаторах v-model
можно прочитать в разделе пользовательских событий.
# Стратегия миграции
Рекомендуется:
проверить кодовую базу на использование
.sync
и заменить их наv-model
:<ChildComponent :title.sync="pageTitle" /> <!-- следует заменить на --> <ChildComponent v-model:title="pageTitle" />
1
2
3
4
5для всех
v-model
без аргументов убедитесь, что изменили входной параметр и имя события наmodelValue
иupdate:modelValue
соответственно<ChildComponent v-model="pageTitle" />
1// ChildComponent.vue export default { props: { modelValue: String // раньше было `value: String` }, emits: ['update:modelValue'], methods: { changePageTitle(title) { this.$emit('update:modelValue', title) // раньше было `this.$emit('input', title)` } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
COMPONENT_V_MODEL
COMPILER_V_BIND_SYNC
# Дальнейшие шаги
Более подробную информацию о новом синтаксисе v-model
можно получить здесь: