вместе сvue3.4
Выпуск версии,defineModel
Также официально стал штатным сотрудником。Это упрощает двустороннюю связь между родительскими и дочерними компонентами.обязательность,В настоящее время это официально рекомендуемая реализация двусторонней обязательности.
vue3.4
Как добиться двунаправленности в прошломобязательностьКаждый должен знатьv-model
Просто синтаксический сахар,Фактически он определен для компонентаmodelValue
Свойства и мониторингupdate:modelValue
событие,Поэтому в прошлом нам приходилось реализовывать двунаправленные данные.обязательность Вам необходимо определить подкомпонентmodelValue
свойство,И для обновления внутри подкомпонентаmodelValue
Требуется, когда значениеemit
выйди одинupdate:modelValue
событие,Передайте новое значение в качестве второго поля.
Давайте рассмотрим простой пример. Код родительского компонента выглядит следующим образом:
<template>
<CommonInput v-model="inputValue" />
</template>
<script setup lang="ts">
import { ref } from "vue";
const inputValue = ref();
</script>
Код подкомпонента следующий:
<template>
<input
:value="props.modelValue"
@input="emit('update:modelValue', $event.target.value)"
/>
</template>
<script setup lang="ts">
const props = defineProps(["modelValue"]);
const emit = defineEmits(["update:modelValue"]);
</script>
Приведенный выше пример должен быть знаком каждому.,Так это было реализовано раньшеv-model
двустороннийобязательностьиз。Но есть проблемаinput
Поле ввода фактически поддерживает прямое использованиеv-model
из,Мы не используем его здесьv-model
Но вinput
Добавьте над полем вводаvalue
свойствоиinput
событие。
Причина в том, что изvue2
Это уже односторонний поток данных с самого начала,Его нельзя изменить непосредственно в подкомпонентах.props
стоимость в。Вместо этого его следует выбросить из дочернего компонентасобытие,Родительский компонент должен отслеживать это событие.,Затем измените родительский компонент, переданный вprops
изпеременная。Если здесь мы дадимinput
Добавьте его прямо в поле вводаv-model="props.modelValue"
,Затем он фактически модифицируется непосредственно внутри подкомпонента.props
серединаизmodelValue
。Из-за одностороннего потока данныхизпричина,vue
Прямая модификация не поддерживается.props
из,Вот почему нам нужно написать код, как указано выше.
defineModel
данные о реализациидвустороннийобязательностьdefineModel
это макрос,Так что не обязательно начинать сvueсерединаimport
импортировать,прямойиспользовать Вот и все Понятно。Этот макрос можно использовать для объявлениядвустороннийобязательность prop, через родительский компонент v-model
использовать.
Код родительского компонента такой же, как и раньше, а именно:
<template>
<CommonInput v-model="inputValue" />
</template>
<script setup lang="ts">
import { ref } from "vue";
const inputValue = ref();
</script>
Код подкомпонента следующий:
<template>
<input v-model="model" />
</template>
<script setup lang="ts">
const model = defineModel();
model.value = "xxx";
</script>
сверхуизпримерсередина我们прямой将defineModel
извозвращаемое значениеиспользоватьv-model
обязательностьприезжатьinputнад полем ввода,Нет необходимости определять modelValue
Свойства и мониторинг update:modelValue
событие,Код стал более кратким。defineModel
извозвращаемое значениеэтоref
,Мы можем сделать это в подкомпонентесередина Исправлятьmodel
переменнаяизценить,иродительский компонентсерединаизinputValue
переменнаяизценить Он также будет обновляться синхронно,Это обеспечивает двунаправленную обязательность.
Тогда возникает вопрос,отvue2
С самого начала это становится односторонним потоком данных.。这里Исправлять子组件изценить后,Также было изменено переменное значение родительского компонента.,Тогда не изменится ли это обратно?vue1
издвустороннийпоток данных Понятно??на самом деле Не такиз,Здесь все еще существует односторонний поток данных.,Далее мы кратко поговорим об этомdefineModel
из Принцип реализации。
defineModel
Фактически, компонент под названиемmodel
изrefпеременнаяиmodelValue
изprops,иwatch
ПонятноpropsсерединаизmodelValue
。когдаprops
серединаизmodelValue
изценить改变后会同步更新model
переменнаяизценить。икогда Изменение внутри дочернего компонентаmodel
переменнаяизценить后会抛出update:modelValue
событие,После того, как родительский компонент получит это событие, он обновит соответствующее переменное значение в родительском компоненте.
Принцип реализации Код выглядит следующим образом:
<template>
<input v-model="model" />
</template>
<script setup lang="ts">
import { ref, watch } from "vue";
const props = defineProps(["modelValue"]);
const emit = defineEmits(["update:modelValue"]);
const model = ref();
watch(
() => props.modelValue,
() => {
model.value = props.modelValue;
}
);
watch(model, () => {
emit("update:modelValue", model.value);
});
</script>
смотреть Понятновышеиз После кода вы должны Понятноразвязатьприезжать Понятно为什么可以在子组件内прямой ИсправлятьdefineModel
извозвращаемое значение后родительский компонентверно应изпеременная Он также будет обновляться синхронно Понятно Бар。我们Исправлятьизна самом деледаdefineModel
возвращатьсяизref
переменная,вместо того, чтобы изменять его напрямуюpropsсерединаизmodelValue
。Метод реализации по-прежнемуиvue3.4
ранее реализованныйдвустороннийобязательность Такой жеиз,толькоdefineModel
Этот макрос помогает нам преобразовать предыдущийиз Эти громоздкиеиз Код для инкапсуляцииприезжатьвнутренняя реализация Понятно。
на самом делеdefineModel
из Исходный кодсерединадаиспользовать customRef и watchSyncEffect осознатьиз,我这里да为Понятно Сделать это проще для всехизпрозрачныйdefineModel
из Принцип реализации Кайдзюизref
иwatch
изпример。Если все правыdefineModel
из Исходный код感兴趣,Пожалуйста, оставьте сообщение в области комментариев,Если есть еще друзья, которым интересно,Статью опубликую в следующем номереdefineModel
Исходный кодизстатья。
defineModel
Как определитьtype
、default
ждатьтеперь этоdefineModel
да声明Понятноодинprop,Это также можно определитьpropизtype
、default
。специфический Код выглядит следующим образом:
const model = defineModel({ type: String, default: "20" });
удалять Понятноподдерживатьtype
иdefault
,Также поддерживаетrequired
иvalidator
,использованиеиопределениеprop
То же, что и всегда。
defineModel
Как реализовать несколько v-model
обязательностьОн также поддерживает несколько реализаций родительского компонента. v-model
обязательность,В это время мы даемdefineModel
проходитьизпервый参数就不даобъект Понятно,Но веревка.
const model1 = defineModel("count1");
const model2 = defineModel("count2");
在родительский компонентсерединаиспользоватьv-model
час Код выглядит следующим образом:
<CommonInput v-model:count1="inputValue1" />
<CommonInput v-model:count2="inputValue2" />
Мы также можем использовать несколькоv-model
серединаопределениеtype
、default
ждать
const model1 = defineModel("count1", {
type: String,
default: "aaa",
});
defineModel
какиспользоватьвстроенныймодификаторисопределениемодификаторЕсли ты хочешьиспользовать系统встроенныйизмодификаторнапримерtrim
,Метод записи родительского компонента остается таким же, как и раньше:
<CommonInput v-model.trim="inputValue" />
Нет необходимости вносить какие-либо изменения в подкомпоненты.,ивыше其他изdefineModel
примерда Такой жеиз:
const model = defineModel();
defineModel
Также поддерживаетсопределениемодификатор,например我们要实现один将输入框из Сделать все буквы заглавнымиизuppercase
сопределениемодификатор,同час也需要использоватьвстроенныйизtrim
модификатор。
Код нашего родительского компонента выглядит следующим образом:
<CommonInput v-model.trim.uppercase="inputValue" />
Наш подкомпонент нужно написать так:
<template>
<input v-model="modelValue" />
</template>
<script setup lang="ts">
const [modelValue, modelModifiers] = defineModel({
// getНам это здесь не нужно
set(value) {
if (modelModifiers.uppercase) {
return value?.toUpperCase();
}
},
});
</script>
В это время мы даемdefineModel
проходить进去изпервый参数就да包含get
и set
методизобъект,когдаверноmodelValue
переменная进行读操作час会走приезжатьget
Зайдите внутрь метода,когдаверноmodelValue
переменная进行写操作час会走приезжатьset
Зайдите внутрь метода。Если вам нужно только перехватывать операции записи,Тогда не нужно писатьget
。
defineModel
извозвращаемое значение也可以развязать构成двапеременная,первыйпеременная就да我们前面几个примеризref
объект,раньше давалv-model
обязательность。второйпеременнаяэтообъект,Какие модификаторы включены?,здесь у нас естьtrim
иuppercase
двамодификатор,такmodelModifiers
изценить为:
{
trim: true,
uppercase: true
}
При вводе в поле ввода,пойдетприезжатьset
внутри метода,а потом позвониvalue?.toUpperCase()
Вот и все实现将输入из Буквы становятся заглавными。
这篇статья介绍ПонятнокакиспользоватьdefineModel
Реализация макросадвустороннийобязательностьа такжеdefineModel
из Принцип реализации。
defineModel
Макрос вернетref
объект,Вы можете напрямую изменить это в подкомпонентеref
объект Сделать задание,Соответствующая переменная в родительском компоненте также будет изменена одновременно.defineModel
на самом деле就да在子组件内определение Понятноодинrefпеременнаяиверно应изprop,Затем соответствующий реквизит отслеживается, и значение refпеременная всегда совпадает со значением соответствующего реквизита. При изменении значения refпеременная в дочернем компоненте событие будет передано в родительский компонент.,Пусть родительский компонент обновит соответствующее переменное значение.,Таким образом достигается двусторонняя обязательность.defineModel({ type: String, default: "20" })
Вот и всеопределениеpropизtype
иdefault
ждать Параметры。defineModel("count")
Вы можете достичь несколькихv-model
обязательность。defineModel()
извозвращаемое значение拿приезжатьmodelModifiers
модификаторобъект,Сотрудничать get
и set
Параметры конвертера реализуют пользовательские модификаторы.