v-model на компонентах и defineModel
↑ 4.1 Vue 3: основы, компоненты, Composition API · ← Предыдущая · → Следующая
Зачем это на собесе
Как реализуется двусторонняя привязка на компонентах и что упростил
defineModel.
Объяснение
v-model на компоненте — сахар: prop modelValue + событие update:modelValue.
<!-- Ручная реализация -->
<script setup>
const props = defineProps<{ modelValue: string }>();
const emit = defineEmits<{ "update:modelValue": [v: string] }>();
</script>
<template><input :value="modelValue" @input="emit('update:modelValue', ($event.target as HTMLInputElement).value)" /></template>
<!-- defineModel (3.4+): ref, синхронизированный с родителем -->
<script setup lang="ts">
const model = defineModel<string>({ default: "" }); // v-model
const qty = defineModel<number>("qty", { required: true }); // v-model:qty
const [text, mods] = defineModel<string, "trim" | "upper">({
set(v) { return mods.trim ? v.trim() : v; }, // модификаторы v-model
});
</script>
<template><input v-model="model" /><button @click="qty++">+</button></template><SearchInput v-model="query" />
<Stepper v-model:qty="count" v-model:unit="unit" />
<TextField v-model.trim="name" />| Особенность | Описание |
|---|---|
Несколько v-model | по аргументу: v-model:title, v-model:size |
| Модификаторы | .trim, .number, свои (modelModifiers) |
defineModel | возвращает ref: запись = emit + локальная копия при отсутствии родителя |
Native <input v-model> | value + input (textarea — input, checkbox — change/checked, select — change) |
Сложные поля: v-model для объекта — эмитьте новый объект (иммутабельно), а не мутируйте.
Нюансы и подводные камни
- Нельзя привязать
v-modelк prop потомка напрямую (v-model="props.x"). - В Vue 2 было
value/input(и.sync): миграция наmodelValue/update:modelValue. - Составные компоненты форм с
v-modelдолжны корректно работать сnull/undefined. - Для
<input v-model>с IME (ввод на CJK) обновление происходит после завершения композиции.
Практика
- Сделайте компонент
TextFieldсdefineModel, поддерживающий.trim. - Реализуйте
Stepperс двумяv-model. - Перепишите старый компонент с ручным
modelValueнаdefineModel.
Вопросы с ответами
Как работает
v-modelна компоненте?Передаёт prop
modelValueи слушает событиеupdate:modelValue.
Что упростил
defineModel?Вместо пары props+emit возвращает
ref, который синхронизируется с родителем.