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 中这样使用:- <template>
-
-
- <p >错误</p>
-
- <ul >
- <li v-for="e in errors.global" v-html="e" />
- </ul>
-
- <form>
-
- <label for="username" >
- 用户名
- *
- </label>
-
- <input
- v-model="username"
- @focus="clearErrors"
- id="username"
- name="username"
- type="text"
- autocomplete="username"
- required
-
- :
- />
-
- <ul >
- <li v-for="e in errors.username" v-html="e" />
- </ul>
-
-
- <button
- type="submit"
-
- :
- >
- <button
- type="submit"
-
- :
- >
- 注册
- </button>
- </button>
-
- </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 绑定到输入框
- [/code]这里主要使用了两个个函数:
- [indent][b]clearErrors[/b]: 当重新开始进行输入时,清除错误状态中的全部错误。
- [/indent][indent][b]hasErrors[/b]: 当对应位置出现错误时,将输入框边框颜色变为红色。
- [/indent]将错误状态显示在输入框下:
- [code] <label for="username" >
- 用户名
- *
- </label>
-
- <input
- ...
- />
-
- <ul >
- <li v-for="e in errors.username" v-html="e" />
- </ul>
复制代码 这里我们使用 标签,使用 errors.username 将对应位置的错误消息依次显示在输入框下。
3.4 全局消息显示在表格顶端
-
- <p >错误</p>
-
- <ul >
- <li v-for="e in errors.global" v-html="e" />
- </ul>
- <form>
- ...
- </form>
复制代码 这里使用 hasErrors('global') 来检测是否有全局错误,并在输入表顶端显示。
3.5 提交按钮在有错误时不允许点击
- <button
- type="submit"
-
- :
- >
- 注册
- </button>
复制代码 这里使用 hasErrors() 来检测错误状态类中是否有任何错误,并据此启用或禁用按钮。
4. 完整案例
如果你需要一个完整案例,这里有:错误状态处理在用户注册场景的案例,前端开源,详见:Github,你也可以访问 Githubstar.pro 来查看网页的效果(一个 Github 互赞平台,前端按本文方式进行错误处理)。
感谢阅读,如果本文对你有帮助,可以订阅我的博客,我将继续分享前后端全栈开发的相关实用经验。祝你开发愉快。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |