如何优化代码中api的请求结构
(注:下面以vue项目为例子)
一. 一般项目中api的调用方式
1. 目录结构
|── src
|── |── utils (工具方法文件夹)
|── |── |── http.js (封装的请求方法)
|── |── views (页面文件夹)
|── |── |── device (可以理解为一级菜单)
|── |── |── |── board(可以理解为二级菜单页面)
|── |── |── |── |── index.vue
2. 常见的api调用形式
第一步: 一般都会在http.js中封装好axios的get,post等方法,利用拦截器统一处理请求前和响应后的逻辑。
将http这个方法绑定在vue实例上,Vue.prototype.$http = http
第二步: 在上面index.vue中调用
复制<script>
export default {
data () {
return {
data: ""
}
},
methods: {
async getData () {
const { data } = await this.$https.get("/url/test")
this.data = data
}
}
</script>
3. 问题
(1) 我们传入的后端地址"/url/test",如果要继续用到,我们还是要重复写一遍 this.$https.get("/url/test");
(2) 当页面中有大量的接口调用就会出现接口地址不易管理的情况,这个能否新建一个文件统一管理?
二. 理想项目中的api组织结构(优化1)
1. 目录结构
我们应该有一个api文件夹,存放当前对应模块的接口
board.js 中是这样定义的
复制import { http } form '@/utils/http.js'
export default {
getBoardData () {
return http.get("/url/test")
}
}
|── src
|── |── utils
|── |── |── http.js
|── |── views
|── |── |── device (可以理解为一级菜单)
|── |── |── |── board(可以理解为二级菜单页面)
|── |── |── |── |── index.vue
|── |── api
|── |── |── common (存放公共的方法)
|── |── |── |── index.js
|── |── |── device (一级菜单名)
|── |── |── |── board.js(二级菜单页面名字)
|── |── |── index.js
2. 调用
在 board的模块下的index.vue中使用
复制<script>
import boardApi from "@/api/device/board.js"
export default {
data () {
return {
data: ""
}
},
methods: {
async getData () {
const { data } = await boardApi.getBoardData()
this.data = datad
}
}
<script>
3. 问题
(1) 每次都要import, 能不能用一个全局变量去加载这些接口文件,$service.getData()的形式
三 . 理想项目中的api组织结构(优化2)
1. webpack的require.context
通过 require.context() 函数来创建自己的 context。
可以给这个函数传入三个参数:一个要搜索的目录,一个标记表示是否还搜索其子目录, 以及一个匹配文件的正则表达式。
复制// 找出当前目录下包括子目录所有以.js结尾的文件
const files = require.context("./",true, "\.js$")
所以我们可以利用webpack的require.context得到我们的文件结构
2. 在api文件夹的index.js
|── src
|── |── utils
|── |── |── http.js
|── |── views
|── |── |── device (可以理解为一级菜单)
|── |── |── |── board(可以理解为二级菜单页面)
|── |── |── |── |── index.vue
|── |── api
|── |── |── common (存放公共的方法)
|── |── |── |── index.js
|── |── |── device (一级菜单名)
|── |── |── |── board.js(二级菜单页面名字)
|── |── |── index.js
复制// api文件的index.js
const files = require.context('./', true, /\.js$/)
const commonApis = {}
files.keys().forEach(key => { //require.context的 keys() 返回一个文件路径匹配数组
if (key === './index.js') {
return false
}
const arr = key.match(/\.\/(.*)\/(.*).js)
/**
* commonApis的结构
* {
* device: {
* getBoardData () {}
* }
*
* }
*/
commonApis[arr[1]] = { ...commonApis[arr[1]], ...files(key).default }
})
export default commonApis
3.调用
复制 //commonApis的结构
{
device: { // 一级菜单名
getBoardData () {}
}
}
以上我们得到了一个commonApis的对象,我们得把它绑定在一个变量上,比如$service
所以需要在 vue.config.js 定义
复制const webpack = require('webpack')
const path = require('path')
function resolve (dir) {
return path.join(__dirname, dir)
}
module.exports = {
// 调整 webpack 配置(放置plugins等)
configureWebpack: {
resolve: {
alias: { // 给路径起别名
service: resolve('src/api/index.js')
}
},
plugins: [
new webpack.ProvidePlugin({ // 自动加载模块的插件
$service: ['service', 'default'],
})
]
}
}
这样就可以在board中index.vue中这样调用
复制<script>
export default {
data () {
return {
data: ""
}
},
methods: {
async getData () {
const { data } = await $service.device.getBoardData()
this.data = data
}
}
</script>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决