前端开发实践与后端开发解耦(一)-- 接口数据mock和接口字段映射

server/2024/10/18 3:28:40/

摘要

众所周知,现在的前后端开发都是独立的,除了一些老项目。但是如果公司的开发流程不规范就可能出现前端开发的阻塞,或者出现得多做一些无用功。正确的开发流程应该是:需求评审–需求确认–后端接口设计并输出文档 – 前/后端开发 – 联调 – 测试 – 上线。这里主要强调优先输出接口设计文档的重要性。

Mock 数据

mock数据的作用是让前端开发不依赖后端的开发进度,减少创建数据的时间,减少联调的时间。但是mock也有自己的局限,对于一些复杂的接口没法很好的兼容,对于下载文件也不太好mock等。下面用 vue3 + vite 举例

安装依赖

npm install vite-plugin-mock -D

配置

src 目录的同级上新建mock文件夹;并在 vite.config.jsplugins 中添加下面配置,联调时将选项中的 enable 设置为 false

javascript">// mock/index.js -- 按模块导入方便管理
import user from './user'
import data from './data'export default [...user, ...data]// vite.config.js
viteMockServe({mockPath: path.resolve(__dirname, '../../mock'),// enable: false,localEnabled: viteEnv.VITE_APP_ENV === 'development',watchFiles: true,
})
如何Mock数据

如何使用的官方文档:
vite-plugin-mock配置中文文档
mock数据如何使用
下面写一些常用的写法,以及对于 Restful Api 该如何通过 mock 的接口拦截;其他的使用请看文档。
说明一下Restful Api 类型的接口:
删除:/api/v1/project/:id 请求方法为: Delete
修改:/api/v1/project/:id 请求方法为: Post
详情:/api/v1/project/:id 请求方法为: Get
某个项目里的其他列表:/api/v1/project/:id/other/list 请求方法为: Get

第一种:非 Restful Api
javascript">[{url: '/dev-api/api/v1/project',method: 'get',response: () => {return Mock.mock({code: 0,msg: 'OK','data|10': [{id: '@guid',name: '@string',desc: '@sentence',created_at: '@integer(1693904305000, 1725526705000)',},],})},},// 有查询参数,以下所有都是通用的{url: '/dev-api/api/v1/project/type/list',method: 'get',response: ({ query }) => {const { ... } = querylet list = ['default']// 根据条件生成listreturn {code: 0,msg: 'OK',data: {list,total: 2,},}},},
]
第二种: Restful Api/api/v1/project/:id,接口参数在后面
javascript">[{url: /\/dev-api\/api\/v1\/project\/*/,method: 'delete',response: () => {return {code: 0,msg: 'OK',data: null,}},},
]
第三种: Restful Api/api/v1/project/:id/other/list,接口参数在中间
javascript">	{url: /\/dev-api\/api\/v1\/project\/[^/]+\/other\/list/,method: 'get',response: () => {return {code: 0,msg: 'OK',data: Mock.mock({id: '@guid',name: '@string',}),}},}

接口字段映射

在我们写表单,写表格时都会绑定一个 prop 属性的值,该值对应的就是后端接口返回的 字段名;传参数时也是后端需要什么前端传什么,如果后端需要的时下划线的参数 project_name,安装前端的代码习惯都是 驼峰命名 的参数名,这时候你可以将驼峰转下划线。这里说一下更好的实践,那就是这一节的主题:接口字段的映射。将后端接口的响应数据,传给后端的请求参数,通过字段映射转换成前端需要的字段名和后端需要的参数名。

实现

src 中新建 field-map 文件夹,按模块新增对应的文件,比如 project.js。下面是具体代码

javascript">import { mapRequestFields, formatDate } from '@/utils/common'export const fieldMap = {name: 'name',description: 'description',creator: 'creator',createdAt: 'created_at',
}// Format project list
export function formatList(data) {return (data?.map(item => ({id: item.id,name: item.name,description: item.description,creator: item.creator,createdAt: formatDate(item.created_at),})) || [])
}export function formatQuery(params) {return mapRequestFields(params, fieldMap)
}
对象类型字段转换的翻转

如果需要将后端的响应对象转换成前端需要的字段名,或者在表格排序时需要将字段转换回去,可以通过下面的方式实现。其他更多的需求可以自己拓展

javascript">export const fieldMapReverse = Object.keys(fieldMap).reduce((acc, key) => {acc[fieldMap[key]] = keyreturn acc
}, {})export function formatQuery(params) {return mapRequestFields(params, fieldMapReverse )
}
mapRequestFields的实现,对请求参数进行转换
javascript">// 未实现嵌套的转换
export function mapRequestFields(obj, map) {const isFormData = obj instanceof FormDataconst mapFields = isFormData ? new FormData() : {}if (isFormData) {for (const [key, value] of obj.entries()) {if (value === 'undefined' || value === null || value === '') returnconst newKey = map[key] || keymapFields.append(newKey, value)}} else {Object.keys(obj).forEach(key => {if (obj[key] === 'undefined' || obj[key] === null || obj[key] === '') returnconst newKey = map[key] || keymapFields[newKey] = obj[key]})}return mapFields
}

http://www.ppmy.cn/server/132663.html

相关文章

基于SpringBoot+Vue的校园周边美食探索及分享平台的设计与实现(带文档)

基于SpringBootVue的校园周边美食探索及分享平台的设计与实现(带文档) 开发语言:Java数据库:MySQL技术:SpringBootMyBatisVue等工具:IDEA/Ecilpse、Navicat、Maven 源码 校园周边美食探索及分享平台是一个旨在为校园用户提供便捷的美食发现和分享服务的系统。该平…

JavaScript函数

一、 函数的定义 和变量类似,函数必须先定义然后才能使用。 使用 function 关键字定义函数。 > function:函数、功能。 【方式 1 函数声明】 function fun() { // 函数语句块 } - function:定义函数的关键字 - fun:函…

为什么inet_ntoa会返回错误的IP地址?

目录 1、调用inet_addr和inet_ntoa实现整型IP与点式字符串之间的转换 1.1、调用inet_addr将点式字符串IP转换成整型IP 1.2、调用inet_ntoa将整型IP转换成点式字符串IP 2、调用inet_ntoa返回错误点式字符串IP的原因分析 3、解决多线程调用inet_ntoa返回错误点式字符串IP的办…

函数地址对齐 __attribute__((aligned(64))) 编译器选项 -falign-functions=4

1, 实验原料 源代码 hello.c #include <stdio.h>#define ALI // __attribute__((aligned(64)))float ALI adddd(float a, float b, float c, float d){ab;ac;ad;return a; }float ALI subbbb(float a, float b, float c, float d) {a- b;a-c;a-d;return a; }int mai…

Java 小游戏《超级马里奥》

文章目录 一、效果展示二、代码编写1. 素材准备2. 创建窗口类3. 创建常量类4. 创建动作类5. 创建关卡类6. 创建障碍物类7. 创建马里奥类8. 编写程序入口 一、效果展示 二、代码编写 1. 素材准备 首先创建一个基本的 java 项目&#xff0c;并将本游戏需要用到的图片素材 image…

实操部署amis-admin

当需要做一个web服务的时候&#xff0c;前端的实现很令我头疼。搜了一圈前端低代码框架后&#xff0c;注意到百度贡献的amis&#xff0c;通过json来写前端&#xff0c;很酷啊。不得不说&#xff0c;一个好的demo项目&#xff0c;真的能让人迅速进入状态&#xff0c;比直接看文档…

从HCI和空口分析HFP通话和eSCO建立

背景 HFP作为经典蓝牙通话建立和断开的协商服务&#xff0c;通话数据则是通过eSCO链路进行传输&#xff0c;下面以手机和蓝牙耳机为例&#xff0c;结合HCI和空口分析从HFP连接建立&#xff0c;到AT命令协商会话&#xff0c;再到eSCO通话数据链路的建立 。 1&#xff1a;HFP连…

this指针—静态成员—单例模式

01 this指针 C是在C语言的基础上发展而来的&#xff0c;第一个C的编译器实际上是将C程序翻译为C语言&#xff0c;然后再使用C语言编译器编译 C语言中没有类的概念&#xff0c;只有结构&#xff0c;函数都是全局函数&#xff0c;没有成员函数的概念 翻译的时候&#xff0c;将cla…