基于SqlSugar的开发框架循序渐进介绍(10)-- 利用axios组件的封装,实现对后端API数据的访问和基类的统一封装处理
在SqlSugar的开发框架的后端,我们基于Web API的封装了统一的返回结果,使得WebAPI的接口返回值更加简洁,而在前端,我们也需要统一对返回的结果进行解析,并获取和Web API接口对应的数据进行展示即可,本篇随笔介绍在Vue3+TypeScript+Vite的项目中,使用基于TypeScript的基类继承的方式,实现对后端接口数据的统一解析处理的封装操作。
1、SqlSugar的开发框架后端Web API的封装
前面介绍到,在SqlSugar的开发框架的后端,我们需要对Web API统一封装返回结果,如对于授权登录的接口,我们的接口定义如下所示。
/// <summary>
/// 登录授权处理
/// </summary>
/// <returns></returns>
[AllowAnonymous]
[HttpPost]
[Route("authenticate")]
public async Task<AuthenticateResultDto> Authenticate(LoginDto dto)
其中的Web API的返回结果定义如下所示。
/// <summary>
/// 授权结果对象
/// </summary>
public class AuthenticateResultDto
{
/// <summary>
/// 令牌信息
/// </summary>
public string? AccessToken { get; set; } /// <summary>
/// 失效秒数
/// </summary>
public int Expires { get; set; } /// <summary>
/// 处理是否成功
/// </summary>
public bool Succes { get; set; } /// <summary>
/// 错误信息
/// </summary>
public string? Error { get; set; }
}
我们注意到 Authenticate 的Web API方法返回的结果是一些简单的业务信息,一般我们返回结果需要在进行统一的封装处理,以便达到统一的外部处理需要。
关于接口数据格式的统一封装,我们定义一个WrapResultFilter,以及需要一个不封装的属性标识DontWrapResultAttribute,默认是统一封装返回的结果。
而对于结果的统一封装,我们只需要在Web API服务启动的时候,加入相关的过滤器处理即可。
//控制器添加自定义过滤器
builder.Services.AddControllers(options=>
{
options.Filters.Add<WrapResultFilter>(); //统一结果封装处理
options.Filters.Add<GlobalExceptionFilter>();//自定义异常处理
});
//所有控制器启动身份验证
builder.Services.AddMvc(options =>
{
options.Filters.Add(new AuthorizeFilter());//所有MVC服务默认添加授权标签
});
如下是Web API统一封装后返回的结果对象。

而对于列表记录的返回,同样是进行了外围的封装。
/// <summary>
/// 获取所有记录
/// </summary>
[HttpGet]
[Route("all")]
[HttpGet]public virtual async Task<ListResultDto<TEntity>> GetAllAsync()

2、利用axios组件对后端API数据的访问和基类的统一封装处理
利用axios组件对后端Web API的调用,基本上是前端开发的标准做法了。
一般来说,我们为了方便,会对原生的axios组件进行一定的封装处理,以便支持更好的调用处理,一般场景的操作就是POST、GET、PUT、DELETE,以及对文件流的上传处理操作,axios的github地址是https://github.com/axios/axios,如果需要可以参考它来做封装处理即可。
本篇随笔基于https://github.com/vbenjs/vue-vben-admin 项目上的axios组件封装进行使用,它对于axios组件的封装比项目https://github.com/xiaoxian521/vue-pure-admin 上的封装更加丰富一些,因此采用它。
利用axios组件,一般是为了方便,采用Typescript对它进行一定的封装,并利于统一对Request和Response的对象统一拦截处理,如Request请求接口调用的时候,根据当前用户的token进行头部信息的注入,获取到接口后,可以对结果内容进行拆解,获得简化后的结果。
例如对于常规的POST、GET、PUT、DELETE的处理,统一进行了调用,根据配置参数进行处理
get<T = any>(
config: AxiosRequestConfig,
options?: RequestOptions
): Promise<T> {
return this.request({ ...config, method: "GET" }, options);
} post<T = any>(
config: AxiosRequestConfig,
options?: RequestOptions
): Promise<T> {
return this.request({ ...config, method: "POST" }, options);
} put<T = any>(
config: AxiosRequestConfig,
options?: RequestOptions
): Promise<T> {
return this.request({ ...config, method: "PUT" }, options);
} delete<T = any>(
config: AxiosRequestConfig,
options?: RequestOptions
): Promise<T> {
return this.request({ ...config, method: "DELETE" }, options);
}
如对于HTTP请求拦截,我们需要在配置信息中加入token令牌信息,如下代码所示。
/**
* @description: 请求拦截器处理
*/
requestInterceptors: (config, options) => {
// 请求之前处理config
const tokenString = getToken();
// console.log(tokenString);
if (tokenString) {
const data = JSON.parse(tokenString) as AuthenticateDto;
const now = new Date().getTime();
const expired = parseInt(data.expires) - now <= 0; // console.log(data, now, expired);
if (expired) {
// token过期刷新
} const token = data.accessToken;
if (
token &&
(config as Recordable)?.requestOptions?.withToken !== false
) {
// jwt token
(config as Recordable).headers.Authorization =
options.authenticationScheme
? `${options.authenticationScheme} ${token}`
: token;
}
} return config;
},
这些我们进行一定的微调即可,大多数情况下,不需要进行太多的设置。
对于统一返回的结果,我们为了方便,统一进行了处理。在前端定义好几个数据类型,最后返回结果result即可。

在以前写过的关于前端Web API的处理文章中,有《循序渐进VUE+Element 前端应用开发(19)--- 后端查询接口和Vue前端的整合》 、《在Bootstrap开发框架基础上增加WebApi+Vue&Element的前端》,都是对相关业务类进行接口的抽象封装,以便于重用服务器的逻辑调用。
Vue&Element的前端的架构设计如下所示。

一般来说,我们页面模块可能会涉及到Store模块,用来存储对应的状态信息,也可能是直接访问API模块,实现数据的调用并展示。在页面开发过程中,多数情况下,不需要Store模块进行交互,一般只需要存储对应页面数据为全局数据状态的情况下,才可能启用Store模块的处理。
通过WebProxy代理的处理,我们可以很容易在前端中实现跨域的处理,不同的路径调用不同的域名地址API都可以,最终转换为本地的API调用,这就是跨域的处理操作。

3、访问后端接口的ES6 基类的封装处理
前端根据框架后端的接口进行前端JS端的类的封装处理,引入了ES6类的概念实现业务基类接口的统一封装,简化代码。
权限模块我们涉及到的用户管理、机构管理、角色管理、菜单管理、功能管理、操作日志、登录日志等业务类,那么这些类继承BaseApi,就会具有相关的接口了,如下所示继承关系。

按照这个思路,我们在BaseApi的ES6类里面定义了对应Web API基类里面的操作方法,如下所示。

这样,我们在创建一个业务类的时候,如果没有特殊的自定义接口,只需要继承基类BaseApi即可具有所有的常规基类方法了。
// 导入API基类对象,默认具有Get/GetAll/Create/Update/Delete/BatchDelete/SaveImport/Count等接口
import BaseApi from "./base-api";
// 业务类自定义接口实现, 通用的接口已经在BaseApi中定义
class Api extends BaseApi {
// 参考下面案例,增加自定义函数
// GET 方法例子
// 根据条件计算记录数量
// async GetCount(params: object) {
// return await this.HttpGet<number>(this.baseurl + "count", params);
// }
// POST 方法例子
// 创建对象
// async Create(data: object) {
// return await this.HttpPost<boolean>(this.baseurl + `create`, data);
// }
// PUT 方法例子
// 更新对象
// async Update(data: object) {
// return await this.HttpPut<boolean>(this.baseurl + `update`, data);
// }
// DELETE 方法例子
// 删除指定ID的对象
// async Delete(id: number | string) {
// return await this.HttpDelete<boolean>(this.baseurl + `${id}`);
// }
}
// 构造客户信息 Api实例,并传递业务类接口地址
export default new Api("/api/customer/");
如果需要一些定制的方法,我们则根据注释的提示和Web API的路径声明进行编写即可,如下是一个自定义接口的处理。
// 根据字典类型获取对应的TreeNodeItem集合(包括id, label属性)
async GetTreeItemByDictType(dictTypeName: string) {
return await this.HttpGet<TreeNodeItem[]>(
this.baseurl + `treeitem-by-typename/${dictTypeName}`
);
}
由于是基于TypeScript,我们在具体的位置中定义了TreeNodeItem类型,对应服务器返回的WebAPI类型即可。
//树节点类型
export interface TreeNodeItem {
id: string;
label: string;
key?: string;
children?: TreeNodeItem[];
}
然后在自定义的ES6类的顶部引入类型定义就可以了
import {
  PagedResult,
  ListResult,
  TreeNodeItem,
  CListItem,
  CommonResult
} from "./types";
我们定义了接口后,就可以在Vue的JS里面进行调用了。
// 使用字典类型,从服务器请求数据
await dictdata.GetTreeItemByDictType(typeName).then(list => {
if (list) {
list.forEach(item => {
dictItems.value.push({ id: item.id, label: item.label });
});
}
});
我们也可以使用async/await的异步线程调用方法,如下所示。

另外,由于我们的ES6接口定义,是基于TypeScript的,它的数据类型可以推断出来,因此在编码或者查看对应属性的时候,会有非常好的提示信息,如上所示。
最后我们来验证下实际的axios调用页面的效果。

以及另外一个复杂一点的测试页面展示。

后续继续介绍Vue3+TypeScript+ElementPlus的相关技术点。
基于SqlSugar的开发框架循序渐进介绍(10)-- 利用axios组件的封装,实现对后端API数据的访问和基类的统一封装处理的更多相关文章
- 基于SqlSugar的开发框架循序渐进介绍(12)-- 拆分页面模块内容为组件,实现分而治之的处理
		
在早期的随笔就介绍过,把常规页面的内容拆分为几个不同的组件,如普通的页面,包括列表查询.详细资料查看.新增资料.编辑资料.导入资料等页面场景,这些内容相对比较独立,而有一定的代码量,本篇随笔介绍基于V ...
 - 基于SqlSugar的开发框架循序渐进介绍(13)-- 基于ElementPlus的上传组件进行封装,便于项目使用
		
在我们实际项目开发过程中,往往需要根据实际情况,对组件进行封装,以更简便的在界面代码中使用,在实际的前端应用中,适当的组件封装,可以减少很多重复的界面代码,并且能够非常简便的使用,本篇随笔介绍基于El ...
 - 基于SqlSugar的开发框架循序渐进介绍(14)-- 基于Vue3+TypeScript的全局对象的注入和使用
		
刚完成一些前端项目的开发,腾出精力来总结一些前端开发的技术点,以及继续完善基于SqlSugar的开发框架循序渐进介绍的系列文章,本篇随笔主要介绍一下基于Vue3+TypeScript的全局对象的注入和 ...
 - 基于SqlSugar的开发框架循序渐进介绍(17)-- 基于CSRedis实现缓存的处理
		
在一个应用系统的开发框架中,往往很多地方需要用到缓存的处理,有些地方是为了便于记录用户的数据,有些地方是为了提高系统的响应速度,如有时候我们在发送一个短信验证码的时候,可以在缓存中设置几分钟的过期时间 ...
 - 基于SqlSugar的开发框架循序渐进介绍(20)-- 在基于UniApp+Vue的移动端实现多条件查询的处理
		
在做一些常规应用的时候,我们往往需要确定条件的内容,以便在后台进行区分的进行精确查询,在移动端,由于受限于屏幕界面的情况,一般会对多个指定的条件进行模糊的搜索,而这个搜索的处理,也是和前者强类型的条件 ...
 - 基于SqlSugar的开发框架循序渐进介绍(21)-- 在工作流列表页面中增加一些转义信息的输出,在后端进行内容转换
		
有时候,为了给前端页面输出内容,有时候我们需要准备和数据库不一样的实体信息,因为数据库可能记录的是一些引用的ID或者特殊字符,那么我们为了避免前端单独的进行转义处理,我们可以在后端进行统一的格式化后再 ...
 - 基于SqlSugar的开发框架循序渐进介绍(3)-- 实现代码生成工具Database2Sharp的整合开发
		
我喜欢在一个项目开发模式成熟的时候,使用代码生成工具Database2Sharp来配套相关的代码生成,对于我介绍的基于SqlSugar的开发框架,从整体架构确定下来后,我就着手为它们量身定做相关的代码 ...
 - 基于SqlSugar的开发框架循序渐进介绍(4)-- 在数据访问基类中对GUID主键进行自动赋值处理
		
我们在设计数据库表的时候,往往为了方便,主键ID一般采用字符串类型或者GUID类型,这样对于数据库表记录的迁移非常方便,而且有时候可以在处理关联记录的时候,提前对应的ID值.但有时候进行数据记录插入的 ...
 - 基于SqlSugar的开发框架循序渐进介绍(5)-- 在服务层使用接口注入方式实现IOC控制反转
		
在前面随笔,我们介绍过这个基于SqlSugar的开发框架,我们区分Interface.Modal.Service三个目录来放置不同的内容,其中Modal是SqlSugar的映射实体,Interface ...
 
随机推荐
- 简单说一说jsonp原理
			
背景:由于浏览器同源策略的限制,非同源下的请求,都会产生跨域问题,jsonp即是为了解决这个问题出现的一种简便解决方案. 同源策略即:同一协议,同一域名,同一端口号.当其中一个不满足时,我们的请求即会 ...
 - 联邦平均算法(Federated Averaging Algorithm,FedAvg)
			
设一共有\(K\)个客户机, 中心服务器初始化模型参数,执行若干轮(round),每轮选取至少1个至多\(K\)个客户机参与训练,接下来每个被选中的客户机同时在自己的本地根据服务器下发的本轮(\(t\ ...
 - Bugku练习题---MISC---easy_nbt
			
Bugku练习题---MISC---easy_nbt flag:flag{Do_u_kN0w_nbt?} 解题步骤: 1.观察题目,下载附件 2.通过观察题目描述和压缩包中的文件,发现这个好像是MC的 ...
 - 一文说透 MySQL JSON 数据类型(收藏)
			
JSON 数据类型是 MySQL 5.7.8 开始支持的.在此之前,只能通过字符类型(CHAR,VARCHAR 或 TEXT )来保存 JSON 文档. 相对字符类型,原生的 JSON 类型具有以下优 ...
 - 操作系统实现-printk
			
博客网址:www.shicoder.top 微信:18223081347 欢迎加群聊天 :452380935 这一次我们来实现最基础,也是最常见的函数print,大家都知道这个是可变参数函数,那具体怎 ...
 - windows 存储和切换 ip 配置
			
我的虚拟机用的是桥接模式,在公司使用时设置的是静态 ip,但网段和家里面的不一样,就导致在公司和家里,我需要频繁修改 ipv4 的配置以适应不同的网络环境 Simple-IP-Config 工具解决了 ...
 - leetcode 643. Maximum Average Subarray I 子数组最大平均数 I
			
一.题目大意 https://leetcode.cn/problems/maximum-average-subarray-i/ 给你一个由 n 个元素组成的整数数组 nums 和一个整数 k . 请你 ...
 - VMWare中CentOS安装VM-Tools
			
查看CD-ROM驱动器的设备信息 可以通过下面几个命令来查看 dmesg命令 dmesg | egrep -i --color 'cdrom|dvd|cd/rw|writer' /proc/sys/d ...
 - 用python实现输入三边判断能否组成三角形
			
# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'sanjiaoxing.py'## Creat ...
 - requests入门
			
1.通过GET请求获得搜索结果的网页源代码 import requests name=input("请输入想要搜索的明星:") url=f'https://www.sogou.co ...