网站搜索

vuetify.js - 使用 TypeScript 和组合式 API 验证 vuetify 表单


我正在尝试在表单提交时进行验证,但在将我找到的示例转换为组合 API 和 TypeScript 时遇到了困难。使用选项 API 时,正确的语法似乎是

if (this.$refs.loginForm.validate()) {....}

并且使用组合式 API,其他帖子建议

if (loginForm.value.validate()) {....}

但是这给了我一个 TS 警告,提示该值可能为 null,更重要的是,即使表单是空提交,if() 条件总是成功的。

我的完整代码如下。valid 变量似乎没有任何影响,所以很明显我使用的方法还有其他问题。:

<script setup lang="ts">
import { ref } from 'vue'

const loginDialog = ref(false)

const userOrEmail = ref('');
const password = ref('');
const showPass = ref(false);
const loginForm = ref(null);
var valid = true;

const nameRules =   [  (value: string) => !!value || 'Required.', ];
const pwRules =     [  (value: string) => !!value || 'Required.', ];

function submit() {

   if (loginForm.value?.validate()) 
   {
        alert("submitted");
        loginDialog.value = false;
    }
}
</script>

<template>
  <v-dialog v-model="loginDialog" activator="parent" width="300">
  <v-card>
    <v-card-title class="headline black" primary-title>
      Sign in 
    </v-card-title>
    <v-card-text class="pa-5">
      <v-form @submit.prevent="submit" ref="loginForm"  v-model="valid" >
        <v-text-field v-model="userOrEmail"  :rules="nameRules"  label="User name or email" hint="Username will be 3 to 10 characters">
        </v-text-field>
        <v-text-field v-model="password" :append-inner-icon="showPass ? 'mdi-eye' : 'mdi-eye-off'"
          @click:append-inner="showPass = !showPass"   :type="showPass ? 'text' : 'password'" 
          hint="password will be at least 6 characters"
          :rules="pwRules"  label="Password">
        </v-text-field>
        <v-btn color="blue" type="submit" block class="mt-2">    Sign in     </v-btn>
       
      </v-form>
    </v-card-text>
  </v-card>
</v-dialog>
</template>

我尝试将一个示例上传到 Vuetify Playground,但它无法运行,出现了一些我不理解的错误

答案#1

在 VForm 上调用 validate() 会返回一个 promise,因此你需要等待它解析:

async function submit() {
  const {valid, errors} = await loginForm.value.validate()
  if (valid) {
    ...

游乐场示例


请注意,当 VForm 接收到来自底层 <form> 元素的提交事件时,它会触发你通过模板引用调用的相同验证函数。然后,它将返回的 Promise 与提交事件合并为一个 SubmitEventPromise,并将其发送到 @submit(参见代码)。所以你实际上是在第二次调用 validate(并且可以不用模板引用):

async function submit(submitEventPromise: SubmitEventPromise) {
  const {valid, errors} = await submitEventPromise
  if (valid) {
    ...

游乐场示例


最后,VForm 有一个 :modelValue 属性,用于指示表单是否有效。与 validate() 函数不同,它是通过对已注册表单输入的观察者来设置的,当所有输入都已验证时会更新(见代码)。

因此,除非所有输入的验证已被手动触发,否则 @update:modelValue 事件只会在 validation() 完成后才会触发,而这本身就不足以替代 @submit 处理函数中的 SubmitEventPromise 参数。如果你想在 @submit 处理函数中依赖 :modelValue 而不等待该 promise,请确保 validate() 至少已完成一次,例如在表单加载时手动触发它。

游乐场示例