封装理念

将所有接口地址都看做 /{Controller}/{Action} 这样的形式

例如/user/getAll,那么Controller就是user,Action就是getAll

层级多一点的情况,例如/module/user/getAll,那么Controller就可以看做是module/user,Action就是getAll

具体情况以实际项目中接口地址自行分析。

介绍一下需要用到的装饰器

类装饰器

Controller

默认使用类的名称作为请求中{Controller}部分,也可以传参重写路径。

方法装饰器

Get

定义一个Get请求
默认使用方法名称作为请求中{Action}部分,也可以传参重写路径。

Post

定义一个Post请求
默认使用方法名称作为请求中{Action}部分,也可以传参重写路径。

如何封装接口请求?

比如接口路径是/user/getAllget方式请求,不带任何参数。

创建UserApi.js文件

具体文件名称按照实际项目规范来即可。
@Controller()
class user {
  @Get()
  getAll () { }
}
// 这里请导出类的实例,方便调用。
// 后文中将只写类的定义,不再写模块导出语句。
export default new user()

这是一个最简单的封装示例。


接口路径是/user/getUserByIdget方式请求,需要传一个id参数

@Controller()
class user {
  /**
   * @param {String} id 用户id
   */
  @Get()
  getUserById (id) {
    return {
      id
    }
  }
}

在方法里面将接口需要的参数返回,装饰器会自动在请求的时候传过去。

这样比较清晰的知道这个接口需要什么参数,也可以给每个参数做注释。

页面调用

import UserApi from './UserApi.js'

// 相当于 axios.get('/user/getAll')
UserApi.getAll()

// 相当于 axios.get('/user/getUserById',{ params: { id: 1 } })
UserApi.getUserById(1)

装饰器的代码实现

先封装一下axios

建立一个http.js文件,通过这个文件来调用发送请求的方法

import axios from 'axios'

const http = axios.create()

// 这里根据项目需要去加你自己的配置

export default http

封装出几个装饰器

建立一个Decorators.js文件

import http from './http'

/**
 * 一定要在Controller Class上使用该装饰器
 * @param {String} name 支持路径重写
 * @returns 
 */
export function Controller (name) {
  return function (target) {
    // 如果没有指定路径,默认路径为Controller的name
    // ! 如果有代码混淆,务必要传入name参数
    if (name === undefined) name = target.name
    // 把路径存到Controller对象上面
    target.controller = name
  }
}

/**
 * 创建一个装饰器
 * @param {*} request 
 */
function createAction (request) {
  /**
   * 支持重写Action的路径
   * @param {String} path
   */
  return function (path) {
    return function (target, name, descriptor) {
      if (path) name = path

      const { value } = descriptor
      const params = value.apply(target, arguments)

      /**
       * 必须在函数里面去获取Controller的路径,因为方法的装饰器比类的装饰器先执行。
       * @returns 
       */
      descriptor.value = function () {
        const controller = target.constructor.controller
        const url = `/${controller}/${name}`

        return request(url, params)
      }
    }
  }
}

export const Get = createAction((url, params) => {
  return http.get(url, { params })
})

export const Post = createAction((url, params) => {
  return http.post(url, params)
})

注意

在打包的时候,为了压缩体积,通常会对代码做混淆。
这样会导致如果@Controller没有传入参数,最终拼接出的接口路径不正确。
比如原本/user/getAll就变成了/a/getAll
原来的class user被打包成了class a


我是好人
2.2k 声望17 粉丝

Erpack 二次封装ant-design-vue,可以看看。