Vue 3 后端错误消息处理范例

techhub 2024-07-14 08:11:00 阅读 89

Vue 3 后端错误消息处理范例

前端如何存储处理后端返回的错误信息,并按不同来源绑定到页面,例如显示在不同输入框的周围。这样即可实现清晰的错误显示。

1. 错误消息格式

前后端消息传递时,我们可以通过 json 的 <code>errors 字段传递错误信息,一个比较好的格式范例为:

{

errors: {

global: ["网络错误"],

password: ["至少需要一个大写字母", "至少需要八位字符"]

}

}

errors 中,字段名代表出错位置(如果是输入框的话,对应错误要显示在框下面),内容为一个数组,每个字符串代表一个错误。

2. 处理函数

可以新建一个 composables 文件夹,以存储各个 components 中共用的逻辑,例如错误消息处理。这里在 composables 文件夹中新建一个 error.ts

import { ref, type Ref } from 'vue';

export interface ErrorFields {

global: string[];

[key: string]: string[];

}

export function useErrorFields(fields: string[]) {

const errors: Ref<ErrorFields> = ref({ global: [], ...fields.reduce((acc, field) => ({ ...acc, [field]: [] }), {}) });

const clearErrors = () => {

for (const field in errors.value) {

errors.value[field] = [];

}

};

const hasErrors = (field?: string) => {

if (field) {

return errors.value[field].length > 0;

}

return Object.values(errors.value).some((field) => field.length > 0);

};

const addError = (field: string, message: string) => {

if (field === '') {

field = 'global';

}

const array = errors.value[field];

if (!array.includes(message)) {

array.push(message);

}

return array;

};

const removeError = (field: string, message?: string) => {

if (field === '') {

field = 'global';

}

if (message) {

errors.value[field] = errors.value[field].filter((m) => m !== message);

} else {

errors.value[field] = [];

}

};

return { errors, clearErrors, hasErrors, addError, removeError };

}

这里我们就定义了错误类及其处理函数。

3. 组件中的使用

定义的 useErrorFields 工具可以在 component 中这样使用:

<script setup lang="ts">code>

import axios from 'axios';

import { computed, onMounted, ref, type Ref } from 'vue';

import { useErrorFields } from '@/composables/error';

const { errors, clearErrors, addError, hasErrors } = useErrorFields(['username', 'password']);

const username = ref('');

function onSubmit() {

const api = axios.create({

baseURL: import.meta.env.VITE_API_URL,

});

api.get("/user/register")

.catch((error) => {

if (error.response && error.response.data && error.response.data.errors) {

errors.value = { ...errors.value, ...error.response.data.errors };

} else if (error.response) {

addError('', '未知错误');

} else {

addError('', '网络错误');

}

})

}

</script>

<template>

<div

v-if="hasErrors('global')"code>

>

<div >

<p >错误</p>

</div>

<ul >

<li v-for="e in errors.global" v-html="e" />code>

</ul>

</div>

<form>

<div>

<label for="username" >code>

用户名

<span >*</span>

</label>

<div >

<input

v-model="username"code>

@focus="clearErrors"code>

name="username"code>

type="text"code>

autocomplete="username"code>

required

:

/>

</div>

<ul >

<li v-for="e in errors.username" v-html="e" />code>

</ul>

</div>

<div>

<button

type="submit"code>

:

>

注册

</button>

</div>

</form>

</template>

接下来,我们一步步解析以上代码。

3.1 根据后端响应更新错误状态

我们首先使用useErrorFields 定义了一个错误状态类:

const { errors, clearErrors, addError, hasErrors } = useErrorFields(['username', 'password']);

这时候,错误状态 errors 中可访问三个字段,并将绑定到页面的不同位置:

global: 全局错误 / 无具体位置的错误 => 显示在表格顶端的单独框中

username: 用户名上的错误 => 显示在 username 输入框下方

password: 密码上的错误 => 显示在 password 输入框下方

接下来,我们需要定义提交函数,例如这里使用 axios 进行后端访问,后端地址用环境变量提供:

function onSubmit() {

const api = axios.create({

baseURL: import.meta.env.VITE_API_URL,

});

api.get("/user/register")

.catch((error) => {

if (error.response && error.response.data && error.response.data.errors) {

errors.value = { ...errors.value, ...error.response.data.errors };

} else if (error.response) {

addError('', '未知错误');

} else {

addError('', '网络错误');

}

})

}

这样,后端返回错误信息时,错误状态会被自动更新。如果出现了网络错误或其他错误,addError类会在 global 字段上增加错误 (使用空字符串为第一个参数,默认添加到global 字段)。

接下来,将错误状态绑定到页面。

3.2绑定到输入框

<input

v-model="username"code>

@focus="clearErrors"code>

name="username"code>

type="text"code>

autocomplete="username"code>

required

:

/>

这里主要使用了两个个函数:

clearErrors: 当重新开始进行输入时,清除错误状态中的全部错误。

hasErrors: 当对应位置出现错误时,将输入框边框颜色变为红色。

将错误状态显示在输入框下:

<div>

<label for="username" >code>

用户名

<span >*</span>

</label>

<div >

<input

...

/>

</div>

<ul >

<li v-for="e in errors.username" v-html="e" />code>

</ul>

</div>

这里我们使用 <li> 标签,使用 errors.username 将对应位置的错误消息依次显示在输入框下。

3.4 全局消息显示在表格顶端

<div

v-if="hasErrors('global')"code>

>

<div >

<p >错误</p>

</div>

<ul >

<li v-for="e in errors.global" v-html="e" />code>

</ul>

</div>

<form>

...

</form>

这里使用 hasErrors('global') 来检测是否有全局错误,并在输入表顶端显示。

3.5 提交按钮在有错误时不允许点击

<button

type="submit"code>

:

>

注册

</button>

这里使用 hasErrors() 来检测错误状态类中是否有任何错误,并据此启用或禁用按钮。

4. 完整案例

如果你需要一个完整案例,这里有:错误状态处理在用户注册场景的案例,前端开源,详见:Github,你也可以访问 Githubstar.pro来查看网页的效果(一个 Github 互赞平台,前端按本文方式进行错误处理)。

感谢阅读,如果本文对你有帮助,可以订阅我的博客,我将继续分享前后端全栈开发的相关实用经验。祝你开发愉快



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。