You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在服务器返回错误时保持Vuetify提交后的表单弹窗打开

如何让Vuetify弹窗表单在服务器返回错误时保持打开

我有一个嵌套在v-dialog中的Vuetify表单,提交时会向服务器发送数据。服务器接收数据时一切正常,但如果服务器返回错误,表单弹窗会关闭,用户需要重新填写所有字段。如何让表单弹窗保持打开,直到收到服务器的正确响应?


原JavaScript代码

async function submit() {
  const {valid} = await signupForm.value?.validate()
  if (valid) {
    const username = userName.value;
    const pass = password1.value;
    const email = eMail.value;

    creds.value = { name: username, pw: pass, email: email, code: 0 };
    
    myFetch(apiMethods.signup,creds.value)
      .then((response) => {
        if (response != null) {
          Alert('Registration',response,'','info','OK');
          signupDialog.value = false;
          emit('doneSignUp');
          }
          else {
            signupDialog.value = true;
          }
      })
  }
}

function cancel() {
    signupDialog.value = false;
    emit('doneSignUp');
}

原模板代码

<template>
  <v-dialog v-model="signupDialog" activator="parent" >
  <v-card>
    <v-card-title class="headline black" primary-title>
      Sign Up to RideHub
    </v-card-title>
    <v-card-text class="pa-5">
      <v-form @submit.prevent ref="signupForm">
        <v-text-field v-model="userName"  :rules="nameRules"  label="User name"></v-text-field>
        <v-text-field v-model="eMail"     :rules="emailRules" label="Email"></v-text-field>
        <v-text-field v-model="password1" :append-inner-icon="showPass ? mdiEye : mdiEyeOff"
          @click:append-inner="showPass = !showPass"   :type="showPass ? 'text' : 'password'" 
          :rules="pwRules"  label="Password">
        </v-text-field>
        <v-text-field v-model="password2" :append-inner-icon="showPass ? mdiEye : mdiEyeOff"
          @click:append-inner="() => (showPass = !showPass)" :type="showPass ? 'text' : 'password'"
          :rules="pwConfirmRules" label="Confirm password">
        </v-text-field>
        <v-btn color="blue" type="submit"  @click="submit()" block class="mt-2">     Submit      </v-btn>
        <v-btn color="blue" variant="outlined" @click="cancel()" block class="mt-2">   Cancel    </v-btn>
      </v-form>
    </v-card-text>

  </v-card>
</v-dialog>
</template>

问题分析

  1. 重复触发提交:提交按钮同时设置了type="submit"和@click="submit()",会导致submit函数被执行两次,可能引发意外的弹窗关闭行为。
  2. 未处理异步错误:myFetch的错误情况(比如网络失败、服务器返回HTTP错误码)没有被捕获,此时代码不会进入then块,若有其他隐式逻辑可能导致弹窗关闭。
  3. 冗余的弹窗状态设置:错误时手动设置signupDialog.value = true没必要,弹窗默认处于打开状态,只需在成功时关闭即可。

修改后的解决方案

1. 调整模板代码

移除提交按钮的@click绑定,直接通过表单的@submit.prevent触发提交逻辑,避免重复执行:

<template>
  <v-dialog v-model="signupDialog" activator="parent" >
  <v-card>
    <v-card-title class="headline black" primary-title>
      Sign Up to RideHub
    </v-card-title>
    <v-card-text class="pa-5">
      <!-- 把submit函数绑定到表单的submit事件 -->
      <v-form @submit.prevent="submit" ref="signupForm">
        <v-text-field v-model="userName"  :rules="nameRules"  label="User name"></v-text-field>
        <v-text-field v-model="eMail"     :rules="emailRules" label="Email"></v-text-field>
        <v-text-field v-model="password1" :append-inner-icon="showPass ? mdiEye : mdiEyeOff"
          @click:append-inner="showPass = !showPass"   :type="showPass ? 'text' : 'password'" 
          :rules="pwRules"  label="Password">
        </v-text-field>
        <v-text-field v-model="password2" :append-inner-icon="showPass ? mdiEye : mdiEyeOff"
          @click:append-inner="() => (showPass = !showPass)" :type="showPass ? 'text' : 'password'"
          :rules="pwConfirmRules" label="Confirm password">
        </v-text-field>
        <!-- 移除@click绑定,仅保留type="submit" -->
        <v-btn color="blue" type="submit" block class="mt-2">Submit</v-btn>
        <v-btn color="blue" variant="outlined" @click="cancel()" block class="mt-2">Cancel</v-btn>
      </v-form>
    </v-card-text>
  </v-card>
</v-dialog>
</template>

2. 优化JavaScript逻辑

使用async/await统一处理异步流程,添加try/catch捕获所有错误,确保只有服务器响应成功时才关闭弹窗:

async function submit() {
  const { valid } = await signupForm.value?.validate()
  if (!valid) return;

  const username = userName.value;
  const pass = password1.value;
  const email = eMail.value;

  creds.value = { name: username, pw: pass, email: email, code: 0 };

  try {
    const response = await myFetch(apiMethods.signup, creds.value);
    if (response != null) {
      Alert('Registration', response, '', 'info', 'OK');
      signupDialog.value = false;
      emit('doneSignUp');
    } else {
      // 服务器返回空响应,提示错误,保持弹窗打开
      Alert('Registration', '提交失败,请重试', '', 'error', 'OK');
    }
  } catch (error) {
    // 捕获网络错误或服务器异常,提示用户并保持弹窗打开
    Alert('Registration', '服务器连接失败,请稍后再试', '', 'error', 'OK');
    // 可选:打印错误信息用于调试
    console.error('提交错误:', error);
  }
}

function cancel() {
  signupDialog.value = false;
  emit('doneSignUp');
}

关键改进点

  • 统一异步处理:用try/catch包裹await myFetch,覆盖所有成功、失败和错误场景。
  • 避免重复提交:移除按钮的@click,仅通过表单submit事件触发逻辑。
  • 精准控制弹窗状态:仅在服务器返回有效响应时关闭弹窗,其他情况保持打开并提示用户。

内容的提问来源于stack exchange,提问作者quilkin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 03:30:05