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

1. 错误消息格式

前后端消息传递时,我们可以通过 json 的 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">
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><divv-if="hasErrors('global')"class="mb-5 rounded-md border-0 shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-500 px-4 py-2"><div class="flex text-red-700 dark:text-rose-400 space-x-2 mb-2"><p class="text-lg font-semibold">错误</p></div><ul class="flex flex-col font-medium tracking-wide text-sm list-disc pl-6"><li v-for="e in errors.global" v-html="e" /></ul></div><form><div><label for="username" class="block text-sm font-medium leading-6">用户名<span class="text-red-700">*</span></label><div class="mt-2"><inputv-model="username"@focus="clearErrors"id="username"name="username"type="text"autocomplete="username"requiredclass="block w-full rounded-md border-0 py-1.5 px-3 shadow-sm ring-1 ring-inset focus:ring-2 focus:ring-inset focus:ring-indigo-600 focus:outline-none sm:text-sm sm:leading-6 dark:bg-white/10 dark:ring-white/20":class="{ 'ring-red-500': hasErrors('username'), 'ring-gray-300': !hasErrors('username') }"/></div><ul class="flex flex-col font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"><li v-for="e in errors.username" v-html="e" /></ul></div><div><buttontype="submit"class="flex w-full justify-center rounded-md px-3 py-1.5 text-sm font-semibold leading-6 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 text-white shadow-sm hover:bg-indigo-500":class="{'cursor-default pointer-events-none': hasErrors() || processing,'bg-gray-400': hasErrors(),'bg-indigo-600': !hasErrors(),}">注册</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 绑定到输入框

<inputv-model="username"@focus="clearErrors"id="username"name="username"type="text"autocomplete="username"requiredclass="block w-full rounded-md border-0 py-1.5 px-3 shadow-sm ring-1 ring-inset focus:ring-2 focus:ring-inset focus:ring-indigo-600 focus:outline-none sm:text-sm sm:leading-6 dark:bg-white/10 dark:ring-white/20":class="{ 'ring-red-500': hasErrors('username'), 'ring-gray-300': !hasErrors('username') }"
/>

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

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

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

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

<div><label for="username" class="block text-sm font-medium leading-6">用户名<span class="text-red-700">*</span></label><div class="mt-2"><input.../></div><ul class="flex flex-col font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"><li v-for="e in errors.username" v-html="e" /></ul>
</div>

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

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

<divv-if="hasErrors('global')"class="mb-5 rounded-md border-0 shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-500 px-4 py-2"
><div class="flex text-red-700 dark:text-rose-400 space-x-2 mb-2"><p class="text-lg font-semibold">错误</p></div><ul class="flex flex-col font-medium tracking-wide text-sm list-disc pl-6"><li v-for="e in errors.global" v-html="e" /></ul>
</div>
<form>...
</form>

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

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

<buttontype="submit"class="flex w-full justify-center rounded-md px-3 py-1.5 text-sm font-semibold leading-6 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 text-white shadow-sm hover:bg-indigo-500":class="{'cursor-default pointer-events-none': hasErrors(),'bg-gray-400': hasErrors(),'bg-indigo-600': !hasErrors(),}"
>注册
</button>

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

4. 完整案例

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/743325.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenDiary 24.7

致敬传奇耐拖王现在是,7 月 13 日。距离上一次写日记过去了 58 天 致敬传奇耐拖王 xiwon那么,在鼠鼠肘赢牢大之前的这段时间,what happened, on earth?五月下旬,前去了西安邀请赛,打的一坨。回来之后写了一点游记,但是居然还没有写完 那么到底为什么没有写完呢?这要从很…

我用cpca 截取地址中的省市区,突然就乱了,这是什么原因

大家好,我是Python进阶者。 一、前言 前几天在Python钻石交流群【逆光】问了一个Python数据处理的问题,问题如下:请问一下 我用cpca 截取地址中的省市区,突然就乱了,这是什么原因? 二、实现过程 这里【瑜亮老师】给了个思路如下:看着好像是行弄乱了。 【不上班能干啥!】…

k8s字段选择器

目录一、概述二、基本语法三、支持的字段1、错误示例2、支持的字段列表四、支持的操作符1、示例五、跨多种资源类型使用字段选择器 一、概述 在Kubernetes中,字段选择器(Field Selectors)和标签选择器(Label Selectors)是两种不同的查询机制,用于过滤和选择特定的资源。字…

three.js+vue污水处理厂数字孪生平台智慧城市web3d

案例效果截图如下: 主场景三维逻辑代码如下:<template><div class="whole"><!-- threejs画布 --><div id="threejs" ref="threejs"></div><!-- 污水厂模型加载进度条 --><a-progress:stroke-color=&quo…

反射DLL注入原理解析

反射 DLL 注入又称 RDI,与常规 DLL 注入不同的是,它不需要 LoadLibrary 这个函数来加载 dll,而是通过 DLL 内部的一个函数来自己把自己加载起来,这么说可能会有一点抽象,总之这个函数会负责解析DLL文件的头信息、导入函数的地址、处理重定位等初始化操作,先不用理解这个函…

Neo4j:图数据库的革命性力量

Neo4j 首席技术官 @prathle 撰写了一篇出色的博文,总结最近围绕 GraphRAG 的热议、我们从一年来帮助用户使用知识图谱 + LLM 构建系统中学到的东西,以及我们认为该领域的发展方向。Neo4j一时间又大火起来,本文将带你快速入门这神奇的数据库。前言 Neo4j是一款符合ACID标准的…

Linux常用文件操作命令

本章将和大家分享Linux常用的文件操作命令。本章将和大家分享Linux常用的文件操作命令。废话不多说,下面我们直接进入主题。 一、目录切换(cd命令) 在Linux系统中,cd 是一个用于切换当前工作目录的命令,它是 "change directory" 的缩写。基本用法如下所示: 1、…

Windows10下的docker容器启动命令docker -v相对路径的挂载目录位置

今天研究docker容器时,启动命令使用到了docker -v test:/app/backend/data 有个从宿主机写入文件到容器这个目录的需求,于是就尝试在宿主机上找到这个test目录 找了一圈都没找到,于是四处搜索,终于在stackoverflow上面找到了 https://stackoverflow.com/questions/61083772…

基于GA遗传优化算法的Okumura-Hata信道参数估计算法matlab仿真

1.算法仿真效果 matlab2022a仿真结果如下(完整代码运行后无水印):2.算法涉及理论知识概要遗传算法(Genetic Algorithm, GA)是一种模拟自然界生物进化过程的全局优化搜索算法,由John Holland于1975年提出。它利用达尔文的自然选择和遗传学原理,通过选择、交叉、变异等操作…

LTPSICE 小知识

1、初值设置:

软件工程进度报告——第二周

本周总结: 本周学习了Java语言的开发软件jdk的下载安装和使用方法,java代码的简单编写 1.下载安装jdk jdk需要在Oracle官网下载,下载地址:www.oracle.com下载时只需选择对应系统的安装包安装即可 2.jdk的安装目录 bin:该路径下存放了各种工具命令,其中比较重要的有:javac…