在最近的网络应用程序中,我们有很多具有相同提交结构的表单:
isSubmitting
变量禁用表单和提交按钮Yup
)isSubmitting
设置回 false 设置并在输入字段上显示 validationErrors
我尝试过使用 vue 3 中的组合 api 进行一些操作。
登录.vue
<template> <div class="min-h-full flex flex-col justify-center py-12 sm:px-6 lg:px-8"> <div class="sm:mx-auto sm:w-full sm:max-w-md"> <h1 class="text-3xl text-center text-gray-900">{{ t('sign_in_account', 1) }}</h1> </div> <div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md"> <div class="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10"> <form @submit.prevent="handleSubmit"> <fieldset :disabled="isSubmitting" class="space-y-6"> <MessageBox v-if="errors.general" :title="errors.general" :messages="errors.messages" /> <Input :label="t('email', 1)" type="text" id="email" v-model="user.email" :error="errors.email" /> <Password :label="t('password', 1)" type="password" id="password" v-model="user.password" :error="errors.password" /> <div class="text-sm text-right"> <router-link class="font-medium text-indigo-600 hover:text-indigo-500" :to="forgotPassword">{{ t('forgot_password', 1) }}</router-link> </div> <SubmitButton class="w-full" :label="t('sign_in', 1)" :submittingLabel="t('sign_in_loader', 1)" :isSubmitting="isSubmitting" /> </fieldset> </form> </div> </div> </div> </template> <script> import { ref } from 'vue'; import { useStore } from 'vuex'; import { useI18n } from 'vue-i18n'; import useForm from '@/use/useForm'; import { validateEmail, LoginValidationSchema } from '@/utils/validators'; export default { setup() { const store = useStore(); const { t } = useI18n({ useScope: 'global' }); const user = ref({ email: '', password: '', }); const { handleSubmit, isSubmitting, errors } = useForm(user, LoginValidationSchema, handleLogin); async function handleLogin(values) { try { return await store.dispatch('auth/login', values); } catch (error) { if (error.response) { console.log(error.reponse); if (error.response.status == 422) { errors.value = { general: `${t('unable_to_login', 1)}<br /> ${t('fix_and_retry', 1)}`, messages: Object.values(error.response.data.errors).flat(), }; } else if (error.response.data.message) { errors.value = { general: error.response.data.message, }; } else { errors.value = { general: `${t('unknown_error', 1)}<br /> ${t('please_try_agin', 1)}`, }; } } else if (error.request) { console.log(error.request); errors.value = { general: `${t('unknown_error', 1)}<br /> ${t('please_try_agin', 1)}`, }; } else { errors.value = { general: `${t('unknown_error', 1)}<br /> ${t('please_try_agin', 1)}`, }; } return; } } return { t, user, handleSubmit, isSubmitting, errors }; }, computed: { forgotPassword() { return validateEmail(this.user.email) ? { name: 'forgotPassword', query: { email: this.user.email } } : { name: 'forgotPassword' }; }, }, }; </script>
useForm.js
import { ref, watch } from 'vue'; export default function useForm(initialValues, validationSchema, callback) { let values = ref(initialValues); let isSubmitting = ref(false); let errors = ref({}); async function handleSubmit() { try { errors.value = {}; await validationSchema.validate(values.value, { abortEarly: false }); isSubmitting.value = true; } catch (err) { console.log('In the catch'); isSubmitting.value = false; err.inner.forEach((error) => { errors.value = { ...errors.value, [error.path]: error.message }; }); } } watch(isSubmitting, () => { if (Object.keys(errors.value).length === 0 && isSubmitting.value) { callback(values); isSubmitting.value = false; } else { isSubmitting.value = false; } }); return { handleSubmit, isSubmitting, errors }; }
这在某种程度上有效,但我错过了两件事。在 useForm
中,我想等到回调完成(成功或失败)才能将 isSubmitting
设置回 false。承诺是做到这一点的好方法吗?还有更好的方法吗?其次,我想要一种可重用的方法来处理 Login.vue
中的错误。有什么建议如何处理这个问题吗?
关于你的第一个问题 -
try..catch
语句有第三个名为finally
的语句,该语句始终在try
语句块完成后执行。
回答你的第二个问题 - 承诺是处理异步逻辑的好方法,包括你发送请求的 API 返回错误响应的情况,然后你可以决定如何处理这种情况下的用户体验。
我不太清楚以可重用的方式处理
Login.vue
中的错误是什么意思,但也许您可以简单地将一个空数组道具传递给名为formErrors
的useForm
并让您的useForm.js
发出一个update:modelValue
事件以获得双向绑定。