在最近的網頁應用程式中,我們有許多具有相同提交結構的表單:
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
事件以獲得雙向綁定。