Постановка проблемы: я только что перенес свое приложение Vue 2 (содержит Vuetify 2) в Vue 3 (с Vuetify 3). После переноса метод validate() в форме не работает должным образом. Он всегда возвращает истинное значение, если в полях формы все еще есть ошибки.
(this.$refs.myForm as any & { validate: () => boolean }).validate()
ИЛИ
(this.$refs.myForm as any).validate()
Вышеприведенная строка кода всегда возвращает обещание (предполагая истинное значение).
Вот ссылка игровой площадки Vuetify (Vue: 3.3.4 и Vuetify: 3.3.7)
Что я пробовал до сих пор?
Я попытался найти основную причину проблемы и пришел к выводу, что this.$refs.myForm.validate() возвращает обещание (я думаю, что компилятор принимает это как истинное значение).
Я думаю, что могу добиться этого, добавив атрибут v-model в элемент формы, а затем при отправке я могу проверить значение формы v-model. Правилен ли этот подход? Или мне нужно что-то изменить в исходном подходе, чтобы он заработал?
Вот площадка ссылка согласно этому подходу.
Если я использую оба решения вместе, оно работает в соответствии с ожиданиями (показывая ошибки проверки и предотвращая отправку, если форма имеет какую-либо ошибку).
Шаблон :
<v-form ref = "myForm" v-model = "valid">
Скрипт:
На кнопке отправки @click событие
if ((this.$refs.myForm as any & { validate: () => boolean }).validate() && this.valid) {
...
}
Приведенное выше решение работает нормально, но все еще думает о лучшем подходе. Если я буду использовать проверку с помощью VForm v-model, это только предотвратит отправку, если есть какие-либо ошибки, но не выделит ошибки.
Обновлять :
Я реализовал решение, предложенное Neha , и оно работает нормально в соответствии с требованиями. Единственное, что я заметил, это то, что если я назначаю правила проверки для метода события нажатия кнопки, проверка не срабатывает для первого поля при первом нажатии, но отлично работает при другом нажатии. Вот игровая площадка Vuetify выпуска.
Чтобы избавиться от этой проблемы, я использую nextTick утилиту vue, и теперь она проверяет все поля при первом нажатии. Вот и рабочая детская площадка. Любой ввод/предложение по этому поводу?
Может быть это полезно
Я использую nextTick() и внутри этого выполняю эту проверку.
@MoritzRingler Я добавил обновление в вопрос. Не могли бы вы посмотреть и внести свой вклад?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


В Vuetify 3 метод validate возвращает обещание, которое можно разрешить либо с помощью await, либо с помощью цепочки ответов с помощью .then(). Пример в документации также демонстрирует, что см. здесь.
Таким образом, одним из подходов к этой проблеме может быть использование переменной ref в форме и при отправке, просто вызовите метод validate() и свяжите его ответ, чтобы извлечь параметр valid, который сообщает статус проверки.
Я использовал скрипт setup в демо. Вот возможное решение-
<template>
<v-form ref = "myForm">
<v-container>
<v-row>
<v-col cols = "12" md = "4">
<v-text-field
v-model = "firstname"
:rules = "nameRules"
:counter = "10"
label = "First name"
required
></v-text-field>
</v-col>
</v-row>
<v-btn type = "submit" color = "primary" @click = "submitForm">Submit</v-btn>
</v-container>
</v-form>
</template>
<script setup lang = "ts">
import { ref } from 'vue'
const myForm = ref();
const firstname = ref(null);
const nameRules = [
value => {
if (value) return true
return 'Name is required.'
},
value => {
if (value?.length <= 10) return true
return 'Name must be less than 10 characters.'
},
]
const submitForm = () => {
myForm.value?.validate().then(({valid: isValid}) => {
console.info(isValid);
})
}
</script>
Надеюсь это поможет.
Спасибо за внимание к проблеме. Ваше решение отлично работает для меня. Я только что добавил обновление к вопросу после того, как реализовал ваше решение. Не могли бы вы взглянуть и внести свой вклад/предложение.
В приведенном вами примере кода вы создаете и назначаете массив правил внутри функции submitForm. Это означает, что каждый раз, когда вы нажимаете кнопку «Отправить», вы сбрасываете правила для обоих полей в один и тот же массив. Реактивное поведение Vue может не переоценивать должным образом эти правила для каждого поля в то время. Так что лучше вынести правила за пределы функции и все заработает.
и по этой причине он работает с nextTick, потому что вы говорите Vue подождать, пока не завершится текущий цикл (сброс правил), а затем подтвердить. Надеюсь это поможет.
Хм, я почти уверен, что ваше решение не сработает в первый раз, так как обработчик @click на кнопке отправки будет запущен до того, как событие отправки будет запущено в VForm или может завершиться любая другая глобальная проверка. Итак, это означает, что при первом нажатии, когда вы делаете:
if ((this.$refs.myForm as any & { validate: () => boolean }).validate() && this.valid) {
...
}
this.$refs.myForm.validate() всегда будет истинным, так как validate() возвращает обещание, а Boolean(new Promise()) истинноthis.valid будет обновляться через v-model после завершения validate() или когда проверка каждого ввода будет запущена вручную (это как это реализовано)При последующих кликах validate() будет запускаться хотя бы один раз, поэтому :modelValue будет отражать текущий статус проверки. Так что в этот момент это работает.
Использование nextTick, как вы предлагаете, заставит выполнение ждать, но для более или менее несвязанного события. Ожидание обещания от validation() является более прямым и надежным подходом и имеет больше смысла семантически, поэтому я бы предложил использовать его.
Поэтому я думаю, что лучшим решением является то, что предлагает Vuetify, где вы ожидаете обещания, переданного обработчику @submit (который также более надежен, чем использование @click на кнопке отправки, поскольку он также охватывает программные отправки):
async function submit(submitEventPromise: SubmitEventPromise) {
const {valid, errors} = await submitEventPromise
if (valid) {
...
(SubmitEventPromise — тип машинописного текста, он экспортируется Vuetify)
Я получаю эту ошибку Cannot find name 'SubmitEventPromise'. Должен ли я импортировать это из любого vue пакета? К вашему сведению, я использую API опций Vue 3.
Также я добавил раздел update в свой пост. Если возможно, я хотел бы услышать ваше предложение о таком поведении.
Ах, тип экспортируется Vuetify, я добавил ссылку на ответ. На вашей игровой площадке вы устанавливаете правила в обработчике отправки, но Vue выполнит обновление после проверки, поэтому во время первой проверки правила будут пустыми. Просто создайте ссылку с правилами вместо пустого массива.
Поскольку у меня есть некоторые ограничения (вызов некоторых служебных методов для проверки некоторых определенных полей), я не могу указать правила во время объявления. Вот почему я помещаю их в метод отправки события.
Ну, тогда вам нужно дождаться nextTick и знать, что проверка отдельных компонентов не будет работать, пока не будет запущена отправка.
Обратите внимание, что при ожидании обновления правил nextTick является правильным событием, так как вы ожидаете обновления привязок компонентов. Валидация происходит независимо от этого и может завершиться после nextTick, так как, например, она может включать получение данных с сервера. Использование nextTick хрупко.
это связано с тем, что новый дизайн vuetify 3 приближается к материальному пользовательскому интерфейсу для поддержки правил Promise. Я рекомендую использовать
awaitвместо того, чтобы пытаться поймать синхронные события, или вы можете предпочесть@submit.prevent