Vue 3 pengendalian ralat boleh guna semula dan pemegang boleh guna semulaSerahkan fungsi dalam "useForm" menggunakan API komposisi
P粉020556231
P粉020556231 2024-03-27 16:23:57
0
1
449

Dalam apl web baru-baru ini, kami mempunyai banyak borang dengan struktur penyerahan yang sama:

  1. Lumpuhkan borang dan butang hantar berdasarkan isSubmitting pembolehubah
  2. Sahkan medan input (kami menggunakan Yup)
  3. Jika pengesahan gagal: tetapkan isSubmitting 设置回 false + 设置并在输入字段上显示 validationErrors kembali kepada palsu + tetapkan dan paparkan Ralat pengesahan pada medan input
  4. Jika pengesahan berjaya: hantar permintaan pos dengan data borang ke api
  5. Jika api ditutup atau mengembalikan ralat, tunjukkan ralat umum

Saya cuba melakukan beberapa operasi menggunakan api gubahan dalam vue 3.

Log masuk.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 };
}

Ini berfungsi sedikit sebanyak, tetapi saya kehilangan dua perkara. Dalam useForm saya mahu menunggu sehingga panggilan balik selesai (berjaya atau gagal) sebelum menetapkan useForm 中,我想等到回调完成(成功或失败)才能将 isSubmitting 设置回 false。承诺是做到这一点的好方法吗?还有更好的方法吗?其次,我想要一种可重用的方法来处理 Login.vue kembali kepada palsu. Adakah komitmen cara yang baik untuk melakukan ini? Adakah terdapat cara yang lebih baik? Kedua, saya mahukan cara yang boleh digunakan semula untuk mengendalikan ralat dalam Login.vue. Sebarang cadangan tentang cara menangani isu ini?

P粉020556231
P粉020556231

membalas semua(1)
P粉301523298

Berkenaan soalan pertama anda - try..catch 语句有第三个名为 finally 的语句,该语句始终在 try blok pernyataan dilaksanakan selepas selesai .

Untuk menjawab soalan kedua anda - Janji ialah cara terbaik untuk mengendalikan logik tak segerak, termasuk situasi di mana API yang anda hantar permintaan untuk mengembalikan respons ralat, dan kemudian anda boleh memutuskan cara mengendalikan pengalaman pengguna dalam kes itu.

Saya tidak pasti apa yang anda maksudkan dengan mengendalikan ralat dalam Login.vue 中的错误是什么意思,但也许您可以简单地将一个空数组道具传递给名为 formErrorsuseForm 并让您的 useForm.js 发出一个update:modelValueLogin.vue dengan cara yang boleh digunakan semula, tetapi mungkin anda boleh menghantar prop tatasusunan kosong kepada

useForm bernama 🎜formErrors code> dan minta 🎜useForm.js anda mengeluarkan acara 🎜update:modelValue untuk mendapatkan pengikatan dua hala. 🎜
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan