前端开发实践与后端开发解耦(一)-- 接口数据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
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值