Vue 项目 API 接口封装2

简介: Vue 项目 API 接口封装2

六、API 接口封装

最后一步,对于 API 接口封装,我们使用面向对象的方式组织数据。

6.1 文件结构划分

在 src 目录下新建 api 目录,然后根据后端 API 接口文档划分模块:

src/api // api interface files
  |_ user // 用户模块
    |_ index.js
  |_ goods // 货物模块
    |_ index.js
  |_ carts // 购物车模块
    |_ index.js
  |_ index.js

6.2 按模块编写

货物模块为例,路径为:src/api/goods/index.js

import axios from '@/utils/request' // axios 实例引入(第五节封装的)
const goods = {
    // 1. 获取所有货物信息
    getGoods: () => axios({
      url: '/api/product1/v1/goods',
      method: 'get'
    }),
    // 2. 获取某条货物信息
    getGoodsById: (id) => axios({
      url: `/api/product1/v1/goods/${id}`,
      method: 'get'
    }),
    // 3. 新增一条货物信息
    addGoods: (data) => axios({
      url: '/api/product1/v1/goods',
      method: 'post',
      data
    }),
    // 4. 删除某条货物信息
    deleteGoodsById: (id) => axios({
      url: `/api/product1/v1/goods/${id}`,
      method: 'delete'
    }),
    // 5. 更新某条货物信息
    // put 与 patch 的区别:put 所有字段均要传递;patch 可选字段传递,不用全部传
    updateGoodsById: (id, data) => axios({
      url: `/api/product1/v1/goods/${id}`,
      method: 'put',
      data
    }),
    // 6. 下载货物报表
    downloadGoodsReport: (data) => axios({
      url: `/api/product1/v1/goods/report`,
      method: 'post',
      data,
      responseType: 'blob' // browser only: 'blob'
    }),
    // 7. 上传货物报表
    uploadGoodsReport: (data) => axios({
      url: `/api/product1/v1/goods/up_report`,
      method: 'post',
      data,
      headers:{"Content-Type": "multipart/form-data"}
    })
}
export default goods

以上,展示了常用的请求形式,包括:GET, POST, PUT/PATCH, DELETE

补充几点:

  • url = base url + request url,其中 base url 就是在 5.1 节中,axios 实例上的 baseURL: process.env.VUE_APP_BASE_URL
  • 第五条更新数据,用了 PUT,其实还有一个类似的 PATCH,他们的区别在上面已经给了注释。PUT 和 PATCH 的区别:stackoverflow.com/questions/2…
  • 发送 POST 请求使用 data ,而发送 GET 请求时,可能需要带上 url 参数,这时候就要用到 params 了。
    举个请求购物车分页数据的例子:http://xxx.yyy.zzz:3000/api/product1/v1/carts?page=1&size=-1
// src/api/carts/index.js
import axios from '@/utils/request'
const carts = {
    // ...
    // 获取购物车信息
    getCarts: (params) => axios({
        url: '/api/product1/v1/carts',
        method: 'get',
        params
    })
}
export default carts

有时候我们还会看到,在发送 POST 请求时,有人会使用 qs ,它的作用是序列化 JSON 格式数据为 urlencoded 格式的字符串。

原因是后端语言处理 JSON 格式的数据比较麻烦,例如 Go 语言的 Gin 框架,传递给它 {Country: Brasil, City: Belo Horizonte} ,为了安全起见,需要开发人员据此单独做结构体,而传递 'Country=Brasil&City=Belo Horizonte' 这样的字符串则更为合适。

这里改写一下货物模块中的第三个 POST 请求,记得首先要引入 qs 模块:

import axios from '@/utils/request'
+ import qs from 'qs' 
const goods = {
    // ...
    // 3. 新增一条货物信息
    addGoods: (data) => axios({
        url: '/api/product1/v1/goods',
        method: 'post',
        data: qs.stringify(data)
    }),
    // ...
}
export default goods
  • 关于urlencoded可以查看以下三篇参考:
  • axios-http.com/docs/urlenc…
  • stackoverflow.com/questions/4…
  • developer.mozilla.org/zh-CN/docs/…

6.3 导出 API 对象

当写完各个模块的 api 请求接口后,就需要导出了。回到第二节的构思,我们想要通过 this.$api.moduleName.methodName(…args) 的形式调用方法发起请求。

进入 src/api/index.js

import user from './user'
import goods from './goods'
import carts from './carts'
// ...
class API {
    constructor () {
        this.user = user
        this.goods = goods
        this.carts = carts
        // ...
    }
}
// 导出使用
export default new API()

6.4 小试牛刀

将 API 实例导出之后,将它挂载到 Vue 原型上,就能正常使用了。

// src/main.js
import API from './api'
Vue.prototype.$api = API
// Test.vue
<template>
    <button @click="handleData">test request</button>
</template>
<script>
export default {
    name: 'Test',
    data () {
        return {
            tableData: []
        }
    },
    methods: {
        fetchData () {
            return this.$api.goods.getGoods()
        },
        async handleData () {
            try {
                const response = await this.fetchData()
                // ...
            } catch (e) {
                console.error(e)
            }
        }
    }
}
</script>

6.5 冗余问题的解决

以上,其实还有一个问题尚未解决,就是每一个请求 api 的 url 里的 /api/product1/v1 都是重复的,这个容易,把它分离出去变成一个模块,自定义 url 前缀。

src/api/url_prefixes.js

function generatePrefix ({productName, version} = {productName: 'product1', version: 'v1'}) {
    return `/api/${productName}/${version}`
}
export const v1 = generatePrefix() // '/api/product1/v1'
export const v2 = generatePrefix({version: 'v2'}) // '/api/product1/v2'
export const p2v2 = generatePrefix({productName: 'product2', version: 'v2'}) // '/api/product2/v2'

从上面可以看到,除了接口版本可能会发生变化,产品名称也是有可能发生变化的,我们也用变量控制。之后,在各模块的 api 文件中就可以用使用变量来控制 url 前缀部分了。

例如改写货物模块的 api url 前缀:

import axios from '@/utils/request' // axios 实例引入(第五节封装的)
import { v1 } from '../**url_prefixes**.js' // 引入前缀:**'/api/product1/v1'**
const goods = {
    // 1. 获取所有货物信息
    getGoods: () => axios({
      url: `${v1}/v1/goods`,
      method: 'get'
    }),
    // 2. 获取某条货物信息
    getGoodsById: (id) => axios({
      url: `${v1}/goods/${id}`,
      method: 'get'
    }),
    // 3. 新增一条货物信息
    addGoods: (data) => axios({
      url: `${v1}/v1/goods`,
      method: 'post',
      data
    }),
    // ...
}
export default goods

至此,三个关键问题都已经得到了解决:

  • 永久性变量冗余
  • 高强度心智负担
  • 模块过于扁平化


七、总结

请求的 API 封装到此就结束了,除了以上这种面向对象的设计以外,还有其他的方式。最后,整理一下封装的整体流程:

  1. 请求 API 结构设计,this.$api.moduleName.methodName(…args)
  2. 脚手架模式与环境变量设置
  3. Axios 封装(包括实例配置和拦截器),导出实例
  4. 请求 API 编写及导出,注意分模块编写
  5. 将 API 挂载到 Vue 实例,正常使用

文章里,我添加了很多参考链接,如有疑惑可以看一看,看完如果仍然有疑惑,那就找人讨论吧,之后这一块内容你应该就可以掌握了。



目录
相关文章
|
1月前
vue3+Ts 二次封装ElementUI form表单
【10月更文挑战第8天】
195 59
|
1月前
|
JavaScript 数据可视化
vue-cli学习一:vue脚手架的 vue-cli2和vue-cli3版本 创建vue项目,vue的初始化详解
这篇文章介绍了如何使用vue-cli 2和3版本来创建Vue项目,并详细说明了两者之间的主要区别。
93 5
vue-cli学习一:vue脚手架的 vue-cli2和vue-cli3版本 创建vue项目,vue的初始化详解
|
1月前
|
JavaScript 容器
乾坤qiankun框架搭建 主应用为vue3的项目。
乾坤qiankun框架搭建 主应用为vue3的项目。
152 2
|
1月前
|
JavaScript
Vue CLi脚手架创建第一个VUE项目
Vue CLi脚手架创建第一个VUE项目
35 3
|
1月前
|
JavaScript API
vue中api统一管理
【10月更文挑战第4天】
|
25天前
|
数据采集 监控 JavaScript
在 Vue 项目中使用预渲染技术
【10月更文挑战第23天】在 Vue 项目中使用预渲染技术是提升 SEO 效果的有效途径之一。通过选择合适的预渲染工具,正确配置和运行预渲染操作,结合其他 SEO 策略,可以实现更好的搜索引擎优化效果。同时,需要不断地监控和优化预渲染效果,以适应不断变化的搜索引擎环境和用户需求。
|
11天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
1月前
|
JavaScript 数据可视化
vue-cli学习二:vue-cli3版本 创建vue项目后,Runtime-Compiler和Runtime-only两个模式详解;vue项目管理器;配置文件的配置在哪,以及如何配置
这篇文章详细介绍了Vue CLI 3版本创建项目时的Runtime-Compiler和Runtime-only两种模式的区别、Vue程序的运行过程、render函数的使用、eslint的关闭方法,以及Vue CLI 2和3版本配置文件的不同和脚手架3版本创建项目的配置文件配置方法。
42 3
vue-cli学习二:vue-cli3版本 创建vue项目后,Runtime-Compiler和Runtime-only两个模式详解;vue项目管理器;配置文件的配置在哪,以及如何配置
|
28天前
|
JavaScript
如何在 Vue 项目中选择合适的模块格式
【10月更文挑战第20天】选择合适的模块格式需要综合考虑多个因素,没有一种绝对正确的选择。需要根据项目的具体情况进行权衡和分析。在实际选择过程中,要保持灵活性,根据项目的发展和变化适时调整模块格式。
21 7
|
24天前
Vue3 项目的 setup 函数
【10月更文挑战第23天】setup` 函数是 Vue3 中非常重要的一个概念,掌握它的使用方法对于开发高效、灵活的 Vue3 组件至关重要。通过不断的实践和探索,你将能够更好地利用 `setup` 函数来构建优秀的 Vue3 项目。