Packaging concept

Treat all interface addresses as /{Controller}/{Action} in the form

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

层级多一点的情况, /module/user/getAll ,那么Controller module/user , Action就是getAll .

The specific situation is analyzed by the interface address in the actual project.

Introduce the decorators that need to be used

class decorator

Controller

By default, the name of the class is used as the {Controller} part of the request. You can also pass parameters to rewrite the path.

method decorator

Get

Define a Get request to use the method name as the {Action} part of the request by default. You can also pass parameters to rewrite the path.

Post

Define a Post request to use the method name as the {Action} part of the request by default, or you can pass parameters to rewrite the path.

How to encapsulate interface requests?

For example, the interface path is /user/getAll , get request without any parameters.

Create UserApi.js file

The specific file name can be based on the actual project specification.
 @Controller()
class user {
  @Get()
  getAll () { }
}
// 这里请导出类的实例,方便调用。
// 后文中将只写类的定义,不再写模块导出语句。
export default new user()

This is the simplest encapsulation example.


The interface path is /user/getUserById , get request, need to pass an id parameter

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

Return the parameters required by the interface in the method, and the decorator will automatically pass it when the request is made.

In this way, it is clearer what parameters this interface needs, and you can also annotate each parameter.

page call

 import UserApi from './UserApi.js'

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

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

Code implementation of the decorator

First package axios

Create a http.js file, and use this file to call the method of sending the request

 import axios from 'axios'

const http = axios.create()

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

export default http

Encapsulate several decorators

Create a Decorators.js file

 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)
})

Notice

When packaging, in order to compress the size, the code is usually obfuscated.
In this way, if @Controller does not pass in parameters, the final spliced interface path is incorrect.
For example, the original /user/getAll becomes /a/getAll .
The original class user was packaged into class a .


我是好人
2.2k 声望17 粉丝

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