前端,把 api 封装到一个文件夹到底有没有必要

2021-08-30 10:29:04 +08:00
 kensoz

最近在改一个 vue 项目,看了很多 api 接口封装的文章,似乎这是主流的处理方式?

于是尝试了一下发现了几个问题。

首先,管理是集中了,不过有点类似于 vuex 的思维方式。看过很多人不提倡把请求放在 vuex 里,而使用就近原则,不过本题的 api 接口封装,虽然只是把一些基本实例写好在导入到模板文件中,但是还是让人感觉到了 vuex 那个味。

其次,修改起来感觉没有独立方便,导入还有改名什么的有点麻烦了,感觉 api 端口修改频率都不如参数的修改高。尤其是需要改名的时候,忘记改一个地方的情况经常发生。

所以想问问,这种方案真的是主流的处理方式嘛?真的有必要嘛?

5612 次点击
所在节点    JavaScript
34 条回复
hackyuan
2021-08-30 10:34:49 +08:00
选中函数名 F2
acthtml
2021-08-30 10:39:26 +08:00
抽象出来,放在一个独立的文件夹主要解决:

1. 多个前端组件可能对同一个 [后端服务复用] 。
2. 组件不依赖于服务,而是依赖于服务的产生的数据,方便 [前端组件的复用] 。
3. 结构清晰,如果后端服务改动,可以很容易做修改。
zarvin
2021-08-30 10:42:00 +08:00
vue 开发全局搜索用得多,看了几个开源项目好像都是这样
shzx1994529
2021-08-30 10:46:51 +08:00
一个路由一个 api.js 呗,这玩意无所谓啊,能让别人看懂就行
Yooe
2021-08-30 10:46:56 +08:00
我怎么记得之前好像看到过这个帖子?= =
Kusoku
2021-08-30 10:47:31 +08:00
小的项目放在一起就是为了方便统一维护,根据模块拆分到不同的小文件也是为了按需要引入,这种组织方式可以适应绝大部分项目的需要。如果按模块划分子文件夹,然后再每个子文件夹再划分各种小文件夹,有部分公共请求也需要单独拿出来,实际上还不如单独用一个文件夹来放请求接口配置的内容,区分公共部分和模块部分,这样清楚明晰方便定位。
chenluo0429
2021-08-30 10:48:48 +08:00
api 接口封装就是为了对组件屏蔽后端的具体实现,同时统一处理接口的变更。
如果有参数变更,封装反而可以通过默认值等手段来快速适配。如果有破坏性的变更需要全部修改,封装的你都能忘记,独立的你就一定改得全?
mozhizhu
2021-08-30 10:49:04 +08:00
你经历过后端改请求方式吗?经历过后端改路由吗?
cydysm
2021-08-30 10:54:19 +08:00
不同项目有不同的处理方式,没有银弹,写得多了就知道怎么办了。
netwjx
2021-08-30 11:03:09 +08:00
没有显著必要, 曾经多年 java 和 dotnet, 熟悉各种 MVC, ORM

在前端领域, 将 ajax 调用抽取成函数, 99%是脱裤子放屁


因为 ajax 请求的代码量很少, 后端是因为这部分业务逻辑比较多, 必须复用

前端就算写 3 遍 ajax 调用, 重复的只有 1~2 行, 所谓封装, 只是将这部分重复的代码, 变成了重复的函数调用, 并没有实质意义, 反而增加了一层映射关系(函数名 -> ajax URL)


不重复的部分是如何生成不同的 ajax 请求参数, 而切实有效的封装, 是真能减少重复业务逻辑的

比如根据业务逻辑

- 规整各种 ajax 请求参数: id 必须转换成有效数字, 而不能是字符串
- 处理 ajax 响应参数: 转换成适合前端使用的格式

另一类需要集中处理的逻辑, 用 ajax 模块插件实现

- 认证和授权, 引导到登录界面, 申请权限界面
- 异常处理, 上报和用户友好提示
- 接口缓存
- 并发控制
libook
2021-08-30 11:07:50 +08:00
抛开场景谈对错都是耍流氓。

一个 Vue 项目是由各种类别的模块组成的(如组件、服务、路由……),对于不同项目来说;不同类别的模块规模不同,比如可能营销项目路由路由巨多、组件和服务很少,后台项目路由很少、组件和服务巨多;模块之间的对应关系也不一样,比如有的项目服务可以被所有组件复用,也有的项目服务是从属于各个组件的,不可跨组件使用。
Vue 提供了项目文件结构的灵活性,那么自然在不同场景下可以设计成不同的文件结构,最终都是服务于开发效率。
Biwood
2021-08-30 11:32:24 +08:00
我也觉得有些多余,明明 request 工具在组建里面直接请求就行了,还要多封装一层,而且这些请求函数复用性特别低,绝大部分都只在一个模块用到了一次而已。真有复用的情况,也是跟着组件一起,而不是单独调用。有种过度设计的感觉。

@libook
楼主说的应该是那种纯粹的 api 封装,只是提前固定了路径和 method 而已,不携带具体的业务数据,你说的“服务”的概念其实已经在 api 基础上做了其他业务逻辑了。
lin07hui
2021-08-30 11:32:46 +08:00
我这边之前的人封装的
// src/api/index.js
export * from "./xxx.js";

// src/api/xxx.js
export const xxxDetail = (id) => { ... };
export const xxxList = ({ page, ... }) => { ... };
export const xxxSave = ({ id, ... } ) => { ... };

// src/store/modules/xxx.js
import { xxxDetail, xxxList, xxxSave } from "@/utils/api";
import { createState } from "@/utils/state";

const options = createState({ detail: { api: xxxDetail, ... }, list: { api: xxxList, ... }, save: { api: xxxSave, ... });

export default {
namespaced: true,
...options
};

// src/utils/state -- 248 行代码
// createState
/**
* Create a store options
* @param {Promise} list.api - 获取分页列表数据接口
* @param {Object} list.params - 发送给接口的参数
* @param {Function} list.beforeSet - 设置数据之前执行,beforeSet(接口数据)
* @param {Promise} detail.api - 获取单条数据接口
* @param {Object} detail.params - 发送给接口的参数
* @param {Promise} save.api - 保存接口
* @param {Function} save.success - 保存成功后运行:success({ commit, state, dispatch }, record)
* ....还有很多
*/
Biwood
2021-08-30 11:34:20 +08:00
当然,如果是 TypeScript 项目,这样写比较方便提前约定前后端字段的对应关系,类似于 adapter 的概念
lin07hui
2021-08-30 11:36:11 +08:00
@lin07hui #13 import { xxxDetail, xxxList, xxxSave } from "@/api";
ansenJ
2021-08-30 11:36:24 +08:00
初期多人开发的时候 别说 API 了 Store Router 都是每人一个文件, 等项目稳定了再汇总的。多人操作一个文件的那位, 你是爱上解决 git 冲突吗?
fernandoxu
2021-08-30 13:35:14 +08:00
按领域组织更好,
Sapp
2021-08-30 14:15:41 +08:00
现在 api 不都是自动生成函数么?还有人手写???
chairuosen
2021-08-30 14:21:03 +08:00
说不需要的都没写过大项目?
cloudzqy
2021-08-30 14:50:31 +08:00
现在基本 typescript 了,基本都封,定义类型比较方便。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/798770

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX