Метод проверки формы () не работает с Vue 3 и Vuetify 3

Постановка проблемы: я только что перенес свое приложение 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, и теперь она проверяет все поля при первом нажатии. Вот и рабочая детская площадка. Любой ввод/предложение по этому поводу?

это связано с тем, что новый дизайн vuetify 3 приближается к материальному пользовательскому интерфейсу для поддержки правил Promise. Я рекомендую использовать await вместо того, чтобы пытаться поймать синхронные события, или вы можете предпочесть @submit.prevent

Tachibana Shin 09.08.2023 14:37

Может быть это полезно

Moritz Ringler 09.08.2023 15:12

Я использую nextTick() и внутри этого выполняю эту проверку.

Rohìt Jíndal 09.08.2023 17:30

@MoritzRingler Я добавил обновление в вопрос. Не могли бы вы посмотреть и внести свой вклад?

Rohìt Jíndal 09.08.2023 17:38
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
4
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В 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>

Вот рабочая демонстрация.

Надеюсь это поможет.

Спасибо за внимание к проблеме. Ваше решение отлично работает для меня. Я только что добавил обновление к вопросу после того, как реализовал ваше решение. Не могли бы вы взглянуть и внести свой вклад/предложение.

Rohìt Jíndal 10.08.2023 14:23

В приведенном вами примере кода вы создаете и назначаете массив правил внутри функции submitForm. Это означает, что каждый раз, когда вы нажимаете кнопку «Отправить», вы сбрасываете правила для обоих полей в один и тот же массив. Реактивное поведение Vue может не переоценивать должным образом эти правила для каждого поля в то время. Так что лучше вынести правила за пределы функции и все заработает.

Neha Soni 10.08.2023 14:41

и по этой причине он работает с nextTick, потому что вы говорите Vue подождать, пока не завершится текущий цикл (сброс правил), а затем подтвердить. Надеюсь это поможет.

Neha Soni 10.08.2023 14:44

Хм, я почти уверен, что ваше решение не сработает в первый раз, так как обработчик @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.

Rohìt Jíndal 10.08.2023 14:30

Также я добавил раздел update в свой пост. Если возможно, я хотел бы услышать ваше предложение о таком поведении.

Rohìt Jíndal 10.08.2023 14:31

Ах, тип экспортируется Vuetify, я добавил ссылку на ответ. На вашей игровой площадке вы устанавливаете правила в обработчике отправки, но Vue выполнит обновление после проверки, поэтому во время первой проверки правила будут пустыми. Просто создайте ссылку с правилами вместо пустого массива.

Moritz Ringler 10.08.2023 14:37

Поскольку у меня есть некоторые ограничения (вызов некоторых служебных методов для проверки некоторых определенных полей), я не могу указать правила во время объявления. Вот почему я помещаю их в метод отправки события.

Rohìt Jíndal 10.08.2023 16:05

Ну, тогда вам нужно дождаться nextTick и знать, что проверка отдельных компонентов не будет работать, пока не будет запущена отправка.

Moritz Ringler 10.08.2023 16:08

Обратите внимание, что при ожидании обновления правил nextTick является правильным событием, так как вы ожидаете обновления привязок компонентов. Валидация происходит независимо от этого и может завершиться после nextTick, так как, например, она может включать получение данных с сервера. Использование nextTick хрупко.

Moritz Ringler 10.08.2023 16:23

Другие вопросы по теме