简单分享一下对于后端返回的状态码,我认为的最优雅的封装方案

本文介绍了一种在前端开发中根据后端返回状态码动态显示标签和颜色的优雅解决方案,通过使用泛型类封装选项列表,使得代码更易于维护和复用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

在前端开发中,我们经常会遇到需要根据后端返回的状态码来显示不同的标签和颜色的情况。比如,我们有一个合同列表,里面的status代表各种不同的意义,我们需要根据status的值来显示对应的标签和颜色。当然,比如有搜索的功能,还涉及到根据状态搜索。例如:

statuslabelcolor
0待签约红色
1生效中绿色
2已到期灰色
3已取消灰色
4未生效灰色
5已作废灰色
6已中止灰色

那么,遇到这种情况你会怎么去写呢?使用v-if判断吗?其实这些东西本身并没有任何技术难点,只不过是开发思维导致每个人写法不同,有的人喜欢用计算属性去各种else if套,有人直接cv大法,每个页面只要使用到都会写出如下代码:

<div v-if="item.status === 0" :style="{ color: 'xxx' }">xxx</div>
<div v-if="item.status === 1" :style="{ color: 'xxx' }">xxx</div>
<div v-if="item.status === 2" :style="{ color: 'xxx' }">xxx</div>
<div v-if="item.status === 3" :style="{ color: 'xxx' }">xxx</div>
<div v-if="item.status === 4" :style="{ color: 'xxx' }">xxx</div>
<div v-if="item.status === 5" :style="{ color: 'xxx' }">xxx</div>
<div v-if="item.status === 6" :style="{ color: 'xxx' }">xxx</div>

结果一套业务写下来,用到这个的页面有一大堆,忽然某一天后端老哥告诉你:这个状态我加了xxx状态你加一下。你又当如何应对?什么?你说批量替换?那你如果布局不同导致某页面会出现如下情况:

<span v-if="item.status === 1" :style="{ color: 'xxx' }">xxx</span>
<span v-if="item.status === 0" :style="{ color: 'xxx' }">xxx</span>
<span v-if="item.status === 2" :style="{ color: 'xxx' }">xxx</span>
<span v-if="item.status === 3" :style="{ color: 'xxx' }">xxx</span>
<span v-if="item.status === 4" :style="{ color: 'xxx' }">xxx</span>
<span v-if="item.status === 5" :style="{ color: 'xxx' }">xxx</span>
<span v-if="item.status === 6" :style="{ color: 'xxx' }">xxx</span>

每个地方写出来的因为各种原因可能会有一点小出入导致批量替换不到。而且涉及到根据状态码搜索的功能也替换不到,那么有没有一种简单和优雅的封装方式,让我们的代码更容易维护和复用呢?

答案是:有!在这边博客中,我将向你介绍一种用类方法封装选项列表的方案,让你可以用一行代码就获取到任何属性的值,无论是标签还是颜色。这样做的好处是:

  • 你可以把相关的数据和逻辑封装在一个类中,提高了内聚性
  • 你可以利用继承多态的特性,来扩展或重写这个类,实现更多的功能或适应更多的场景。
  • 你可以利用构造函数静态方法来初始化或创建这个类的实例,提高了灵活性

定义一个接口

首先,我们需要定义一个接口,表示选项对象。一个选项对象包含三个属性:label(标签),value(值),style(样式)。我们可以用TypeScript来定义这个接口,如下:

// 定义一个接口,表示选项对象
interface IOptionItem<T> {
    label: string;
    value: T;
    style?: CSSProperties;
}

复制

注意,我们用了一个泛型参数T来表示value的类型,这样我们就可以让这个接口支持不同类型的值,比如数字、字符串、布尔值等。

定义一个泛型类

接下来,我们需要定义一个泛型类,表示选项列表。一个选项列表包含一个私有属性options(选项数组),和一个公共方法get(根据值获取对应的属性)。我们可以用TypeScript来定义这个泛型类,如下:

// 定义一个泛型类,表示选项列表
class OptionList<T> {
    // 存储选项列表
    options: IOptionItem<T>[] = [];

    // 定义一个构造函数,接收一个选项列表作为参数
    constructor(optionList: IOptionItem<T>[]) {
        this.options = optionList;
    }

    // 定义一个通用方法,根据值获取对应的属性
    public get<K extends keyof IOptionItem<T>>(value: T, key: K) {
        return this.options.find(v => v.value === value)?.[key];
    }
}

复制

注意,我们用了一个泛型参数T来表示选项列表的类型,这样我们就可以让这个类支持不同类型的选项列表,比如数字、字符串、布尔值等。我们还用了一个泛型参数K来表示选项对象的属性名,这样我们就可以让这个方法返回任何属性的值,比如label、value、style等。

创建一个选项列表的实例

最后,我们需要创建一个选项列表的实例,用来存储合同状态的选项和颜色。我们可以用TypeScript来创建这个实例,如下:

// 创建一个选项列表的实例
const contractStatusOptions = new OptionList<number>([
    { label: "待签约", value: 0, style: { color: "red",'--bg-color':'#1899ff' } },
    { label: "生效中", value: 1, style: { color: "green" } },
    { label: "已到期", value: 2, style: { color: "gray" } },
    { label: "已取消", value: 3, style: { color: "gray" } },
    { label: "未生效", value: 4, style: { color: "gray" } },
    { label: "已作废", value: 5, style: { color: "gray" } },
    { label: "已中止", value: 6, style: { color: "gray" } }
]);

复制

注意,我们用了number类型作为选项列表的类型,因为合同状态的值是数字。我们还给每个选项对象添加了一个style属性,用来存储颜色。

调用通用方法,获取标签和样式

现在,我们可以用这个实例来调用通用方法,根据状态值获取对应的标签和样式。我们可以用TypeScript来调用这个方法,如下:

// 调用通用方法,获取标签和样式
contractStatusOptions.get(1, 'label'); // 生效中
contractStatusOptions.get(1, 'style'); // { color: "green" }

复制

注意,我们传入了两个参数:状态值和属性名。这样,我们就可以用一行代码就获取到任何属性的值,无论是标签还是颜色。

总结

在本文中,我向你介绍了一种用类方法封装选项列表的方案,让你可以用一行代码就获取到任何属性的值,无论是标签还是颜色。这样做的好处是:

  • 你可以把相关的数据和逻辑封装在一个类中,提高了内聚性
  • 你可以利用继承多态的特性,来扩展或重写这个类,实现更多的功能或适应更多的场景。
  • 你可以利用构造函数静态方法来初始化或创建这个类的实例,提高了灵活性

我希望你能从这篇文章中学到一些有用的知识,并且能够在你自己的项目中应用这种封装方案。如果你有任何问题或想法或者有更加适合的封装方案欢迎讨论!

<think>好的,我需要处理用户的请求,用户希望获得完整的代示例,特别是关于优雅封装Axios请求的Vue项目实战内容。首先,我需要回顾用户提供的引用内容,尤其是引用[2],其中提到了Vue项目中对Axios的封装,包括统一请求管理、错误处理、简洁的API调用方式等。 接下来,我需要确保生成的代符合用户的要求,并且结构清晰。用户可能希望看到如何创建Axios实例、设置拦截器、统一处理响应和错误,以及如何导出API方法供组件使用。此外,用户可能还需要了解如何在不同环境中配置基础URL,比如开发和生产环境。 然后,我要检查代的正确性,确保语法正确,使用ES6的语法,比如async/await,箭头函数等。同时,要处理请求和响应拦截器,添加常见的功能如请求头设置、加载状态管理、错误提示。对于错误处理,需要区分HTTP状态码和业务逻辑错误,比如后端返回自定义错误。 还需要考虑代的可维护性和扩展性,比如将API请求方法统一放在一个文件中,方便后续添加或修改接口。同时,要处理取消请求的功能,避免组件卸载时可能存在的 pending 请求。 后,需要生成相关问题,这些问题应该围绕Axios封装的不同方面,比如如何进一步优化、如何处理特定错误、如何添加请求重试机制等,帮助用户深入理解相关内容。确保问题具有针对性,能够引导用户进一步学习或解决可能遇到的问题。 在整理过程中,要确保遵循用户提供的系统级指令,使用正确的中文描述,行内公式用$...$,独立公式用$$...$$(虽然在这个回答中可能用不到数学公式,但需要注意其他格式要求)。同时,在引用部分正确添加引用标识,例如引用[2]中的内容。 现在开始编写代示例,分步骤解释每个部分的作用,并确保代完整且可运行。完成后,生成相关问题,帮助用户进一步探索相关主题。</think>关于Vue项目中Axios的优雅封装,以下是完整的实现方案,包含请求拦截、响应处理和错误管理: ### 一、Axios基础封装(src/utils/request.js) ```javascript import axios from &#39;axios&#39; import { ElMessage } from &#39;element-plus&#39; // 创建axios实例 const service = axios.create({ baseURL: process.env.VUE_APP_BASE_API, timeout: 10000, headers: { &#39;Content-Type&#39;: &#39;application/json;charset=UTF-8&#39; } }) // 请求拦截器 service.interceptors.request.use( config => { // 携带token逻辑 const token = localStorage.getItem(&#39;token&#39;) if (token) { config.headers[&#39;Authorization&#39;] = `Bearer ${token}` } // 全局loading状态 store.commit(&#39;SET_LOADING&#39;, true) return config }, error => { store.commit(&#39;SET_LOADING&#39;, false) return Promise.reject(error) } ) // 响应拦截器 service.interceptors.response.use( response => { store.commit(&#39;SET_LOADING&#39;, false) // 处理二进制数据 if (response.config.responseType === &#39;blob&#39;) { return response.data } const res = response.data // 自定义状态码处理 if (res.code !== 200) { ElMessage.error(res.message || &#39;Error&#39;) return Promise.reject(new Error(res.message || &#39;Error&#39;)) } return res }, error => { store.commit(&#39;SET_LOADING&#39;, false) // HTTP状态码处理 if (error.response) { switch (error.response.status) { case 401: router.replace(&#39;/login&#39;) break case 403: ElMessage.error(&#39;拒绝访问&#39;) break case 404: ElMessage.error(&#39;资源不存在&#39;) break case 500: ElMessage.error(&#39;服务器错误&#39;) break default: ElMessage.error(error.message) } } return Promise.reject(error) } ) export default service ``` ### 二、API模块封装(src/api/index.js) ```javascript import request from &#39;@/utils/request&#39; // 用户相关接口 export const userApi = { login(data) { return request({ url: &#39;/user/login&#39;, method: &#39;post&#39;, data }) }, getInfo() { return request({ url: &#39;/user/info&#39;, method: &#39;get&#39; }) } } // 数据接口 export const dataApi = { fetchList(params) { return request({ url: &#39;/data/list&#39;, method: &#39;get&#39;, params }) } } ``` ### 三、组件调用示例(src/views/User.vue) ```javascript import { userApi } from &#39;@/api&#39; export default { methods: { async handleLogin() { try { const res = await userApi.login({ username: &#39;admin&#39;, password: &#39;123456&#39; }) console.log(&#39;登录成功:&#39;, res) } catch (error) { console.error(&#39;登录失败:&#39;, error) } } } } ``` 该方案实现以下核心功能: 1. 环境配置自动切换(通过$VUE_APP_BASE_API) 2. 全局Loading状态管理 3. 自动Token注入 4. 响应数据格式统一处理 5. 错误分级处理(网络错误、HTTP错误、业务错误) 6. 支持二进制文件下载 7. 模块化API管理[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值