自学内容网 自学内容网

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

摘要

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

Mock 数据

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

安装依赖

npm install vite-plugin-mock -D

配置

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

// 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
[
{
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 { ... } = query
let list = ['default']
// 根据条件生成list

return {
code: 0,
msg: 'OK',
data: {
list,
total: 2,
},
}
},
},
]
第二种: Restful Api/api/v1/project/:id,接口参数在后面
[
{
url: /\/dev-api\/api\/v1\/project\/*/,
method: 'delete',
response: () => {
return {
code: 0,
msg: 'OK',
data: null,
}
},
},
]
第三种: Restful Api/api/v1/project/:id/other/list,接口参数在中间
{
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。下面是具体代码

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)
}

对象类型字段转换的翻转

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

export const fieldMapReverse = Object.keys(fieldMap).reduce((acc, key) => {
acc[fieldMap[key]] = key
return acc
}, {})

export function formatQuery(params) {
return mapRequestFields(params, fieldMapReverse )
}
mapRequestFields的实现,对请求参数进行转换
// 未实现嵌套的转换
export function mapRequestFields(obj, map) {
const isFormData = obj instanceof FormData
const mapFields = isFormData ? new FormData() : {}

if (isFormData) {
for (const [key, value] of obj.entries()) {
if (value === 'undefined' || value === null || value === '') return
const newKey = map[key] || key
mapFields.append(newKey, value)
}
} else {
Object.keys(obj).forEach(key => {
if (obj[key] === 'undefined' || obj[key] === null || obj[key] === '') return
const newKey = map[key] || key
mapFields[newKey] = obj[key]
})
}

return mapFields
}

原文地址:https://blog.csdn.net/qq_41068362/article/details/142913714

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!