内部接口开发文档的技术点汇总

每个互联网开发公司,内部都少不了前端和接口的开发人员,而在开发过程中,最不可缺少的就是接口文档。

我司当然也不例外,自从几年前将前后端分离,拆分出前端组和接口组时,我就写了一份给接口组用的接口文档模版的静态页面。

其实就是简单的两个页面,一个列表页,一个详情页,接口人员直接在 PHP 里将拼装好数据的 HTML 代码输出到页面上,就有了接口文档。

而这份文档的界面风格,一用就是这么多年,经历了上百个项目,终于在前几天,实在有点看不过去了,借着手头没什么工作任务,用了3-4天时间,和一位接口小伙伴配合,整了一份全新的接口文档模版出来。

因为这个属于技术部内部自产自销的产品,一切目标就是「为了让内部开发小伙伴用得爽」为前提,所以在UI、交互方面,都是自己说得算,开发过程极度愉悦。

而这篇文章就是要回顾一下,我在这3-4天的时间里,到底做了些什么,有什么小亮点、小技巧。

文档与接口分离

其实就是前后端分离,接口的小伙伴把原先在 PHP 里拼装 HTML 的那部分代码,转为接口的形式提供给我,让我可以更自由的去实现我想要的界面效果。

拆分后其实就两个接口,一个列表页的接口,和一个详情页的接口。

技术框架选型

原先的文档由于没有使用任何技术框架,整体使用起来特别繁琐。例如为了解决进入从列表页进入详情页后,再返回列表页,还能回到原先位置,当时用了一个最硬核的办法:打开新页面。直接就导致看了几个接口详情页后,浏览器上面就开了一排整整齐齐的选项卡。

所以在框架的选择上,打算是做成 SPA(单页面应用)的形式,就直接使用 Vue 了,同时为了美化并统一界面风格,还使用饿了么的 Element 做为基础组件库。

页面缓存

既然做成了 SPA,那就必须要面对页面缓存的痛点,如何从列表页进入详情页后,再返回列表页,还能回到原先位置,就需要使用到 <keep-alive></keep-alive> 这个标签了。

这部分的知识点我之前单独整理过一篇文章:《使用 keep-alive 的 include 属性实现 Vue 页面缓存

页面布局

布局并没有太多亮点,中规中矩的一个顶部导航外加左右分栏的布局,同时右侧主内容区支持宽度自适应。

这里有个不大不小的技术难点,因为我使用了 Flex 左侧固定右侧自适应布局,导致 Element 的表格组件会以一个固定宽度展示,也导致了右侧布局无法自适应。

解决办法就是给自适应的容器增加 overflow: hidden; 样式。

CSS3 计数器

结合伪类一起使用,方便实现了栏目序号的展示。

滚动嵌套

由于左侧导航如果栏目过多,会出现滚动条,同时页面本身也有滚动条,就会导致如上图的效果:当鼠标在左侧导航区域内滚动,滚到底部如果继续滚动,会触发父级,也就是页面的滚动。

解决办法就是给左侧导航增加 overscroll-behavior: contain; 样式。

本地搜索

因为列表接口已经返回了所有接口的路径和名称信息,所以搭配上 Element 的 <el-autocomplete></el-autocomplete> 组件就可以实现本地搜索。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
search(queryString, cb) {
let results = []
this.$store.state.global.interface.map(item => {
item.kind.map(item2 => {
if (item2.req.indexOf(queryString.toLowerCase()) >= 0 || item2.summary.toLowerCase().indexOf(queryString.toLowerCase()) >= 0) {
results.push({
value: item2.req,
info: item2.summary
})
}
})
})
cb(results)
}

通过 indexOf() 模拟模糊查询,同时使用 toLowerCase() 方法,避免因为大小写不同导致查询不到结果。

波浪线动画

不是原创技术,感兴趣的看结尾部分的参考文章链接吧。

面包屑导航

按照一般开发流程,大家都是一个模块一个模块进行接口集成,在查阅文档的时候,也是先进入一个接口的详情页,当这个接口集成完毕后,会需要立马查看该模块下的其它接口。

所以我在面包屑导航上做了一点处理,就是增加模块的下拉列表,方便快速预览并切换至其它接口。因为列表接口的数据存放在全局,所以这块数据上的处理,也是在本地进行过滤筛选的。

关于这个功能,我还做过一系列的思考,一开始我会觉得这功能会不会有点累赘,因为进入详情页后,左侧会切换为有两级结构的导航,完全可以在左侧导航直接切换,甚至也可以立马切换到其它模块下的接口。

但在自己实际使用的过程中发现这两个功能并不冲突,左侧导航更多的使用场景还是在“切换其它模块接口”上,因为它的两级结构,所以展示形式就做成了折叠菜单的效果。而折叠菜单就会有个问题,如上图所示,我所在的页面是“验证码”模块下的,而左侧导航因为我人为点击操作过,展开的是“客户”模块,这时候我如果想看“验证码”模块下的其它接口,我必须先找到“验证码”模块在左侧导航的什么位置,如果模块很多,找起来就会比较花时间了。

复制到剪贴板

我一度觉得复制功能才是接口文档的核心需求,因为不管是手动选取按 Ctrl+C 进行复制,还是在开发的时候直接手打,都有可能会出现复制不全或者敲错的情况,而复制功能就能大幅减少这个情况的出现。所以我在详情页里大量使用到了复制,例如路径、完整链接、参数名、默认值、可选值等等,都支持一键复制到剪贴板。

可选值预览

老的接口文档里可选值查看是直接放在说明里展示,如果可选值比较多的情况下,看起来会不够直观。所以在新版本里,可选值的预览会更加一目了然。

接口测试

因为详情接口里已经把接口请求参数的信息都提供给我了,所以完完全全可以做一个简单的接口测试页面。

这个接口测试的功能一来方便接口开发小伙伴的自测,因为接口开发有套固定的标准,接口文档是自动生成的,所以原先写完一个接口,自测就需要借助 Postman 等工具,将地址和参数一个个填进去才能进行,现在只需要配置几个参数的值就可以进行测试了。

二来对前端也方便了一些,如果接口入参比较多,例如一个复杂的表单,前端在接口集成前可以先进行测试,看下预期效果是怎么样的,方便在接口集成过程中可以进行比对。

三来方便了测试人员进行测试,例如一些复杂的业务场景需要进行一些边界值测试,通过这个功能可以提高测试效率。

当然了,如果接口报错,我说的不是业务逻辑层面的报错,而是代码层面的报错,也可以很清晰的展示出来。

Axios GET 请求如何带数组

1
2
3
4
5
6
7
8
9
10
11
12
axios.get(api_url, {
params: {
token: '123',
type: 'COMPANY_BANK',
list: [
{
token: '123',
type: 'COMPANY_BANK'
}
]
}
})

上面的这段 GET 请求,在实际请求里,是这个样子的:

这显然不是我想要的结构,搜寻一番后,解决方案如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import qs from 'qs'

let params = {
token: '123',
type: 'COMPANY_BANK',
list: [
{
token: '123',
type: 'COMPANY_BANK'
}
]
}
axios.get(api_url, {
params: params,
paramsSerializer: function(params) {
return qs.stringify(params, {arrayFormat: 'indices'})
}
})

CDN 支持

因为使用了 Vue 三件套和 Element 组件,并且还用到了蛮多第三方的依赖包,例如复制(vue-clipboard2)、代码高亮(codemirror)、接口请求(axios)等等,导致项目打包出来后的体积比较大。

考虑到最终打包出来的代码会部署到每个项目的目录下,所以这些第三方的依赖包完全可以通过 CDN 的方式引入进来,减小项目体积的同时,还能得到 CDN 加速的优势。

关于在 Vue 项目中如何实现 CDN 支持,我之前也写过一篇文章《给 Vue 项目中的 vendor.js 文件瘦身》,当然我还是更推荐使用我司开发的 Vue 项目模版,通过简单的配置就可以一键开启 CDN 支持,除了 CDN 支持,还有其它很多不错的特性。

浙江易网科技股份有限公司/vue-automation

总结

做完这个产品,我突然能感受到什么叫「厚积而薄发」,文章中很多技术点看似一两句话就带过了,但这些都是我在曾经项目开发中踩过的坑,熬了几个夜晚(想了想还是不夸大其词写“无数个夜晚”了,因为通宵解决bug的次数两只手都能数得过来)才总结出的经验,所以才能在3-4天的时间里完成从构思到开发,再到交互优化,最终拿出一个至少能让自己看得过去的成品。

参考