Skip to content

数据联调

开发环境

如果前端应用和后端接口服务器没有运行在同一个主机上,你需要在开发环境下将接口请求代理到接口服务器。

如果是同一个主机,可以直接请求具体的接口地址。

配置

开发环境时候,接口地址在项目根目录下

.env.development 文件配置

bash
# vite 本地跨域代理
VITE_PROXY=[["/api","https://xxx.test.com"]]
# 接口地址通用前缀
VITE_GLOB_API_URL=/manage

TIP

  • .env 文件中的字段如果是字符串,则无需加引号,默认全部为字符串
  • VITE_PROXY 不能换行

跨域处理

如果你在 src/api/ 下面的接口为下方代码,且 .env.development 文件配置如下注释,则在控制台看到的地址为 https://xxx.test.com/api/manage/auth/index

由于 /api 匹配到了设置的 VITE_PROXY,所以上方实际是请求 **https://xxx.test.com/manage//auth/index**,这样同时也解决了跨域问题。

跨域原理解析

vite.config.ts 配置文件中,提供了 server 的 proxy 功能,用于代理 API 请求。

ts
server: {
  proxy: {
    "/api":{
      target: 'https://xxx.test.com',
      changeOrigin: true,
      ws: true,
      rewrite: (path) => path.replace(new RegExp(`^/api`), ''),
    }
  },
},

注意

从浏览器控制台的 Network 看,请求是 https://xxx.test.com/api/xxx,这是因为 proxy 配置不会改变本地请求的 url。

生产环境

生产环境接口地址在项目根目录下 .env.production 文件配置。

生产环境接口地址值需要修改 VITE_GLOB_API_URL

如果出现跨域问题,可以使用 nginx 或者后台开启 cors 进行处理, 或者前段处理

打包后如何进行地址修改?

VITE_GLOB_* 开头的变量会在打包的时候注入 _app.config.js 文件内。

dist/_app.config.js 修改相应的接口地址后刷新页面即可,不需要在根据不同环境打包多次,一次打包可以用于多个不同接口环境的部署。

接口请求

进行了特别复杂的封装, 使代码更加模块化, 参考了vben项目

在 vite-project 中:

  1. 页面交互操作;
  2. 调用统一管理的 api 请求函数;
  3. 使用封装的 axios.ts 发送请求;
  4. 获取服务端返回数据
  5. 更新 data;

接口统一存放于 src/api/ 下面管理

以菜单为例:

src/api/ 内新建模块文件,其中参数与返回值最好定义一下类型,方便校验。虽然麻烦,但是后续维护字段很方便。

TIP

类型定义文件可以抽取出去统一管理,具体参考项目

ts
import { IMenuData } from '#/router';
import { defHttp } from '@/http/axios';

enum Api {
    authList = '/auth/index',
}

// 角色-列表
export function api_manage_auth_list() {
    return defHttp.get<Result<Record<'table_list', IMenuData[]>>>({url: Api.authList});
}

axios 配置

axios 请求封装存放于 src/http/axios 文件夹内部

二次封装的 axios 暴露出了 4个方法

js
export declare abstract class CustomAxiosTransform {
    customRequest?: (config: AxiosRequestConfig) => AxiosRequestConfig; // 自定义请求拦截
    customResponse?: (config: AxiosResponse<any>) => AxiosResponse<any>; // 自定义相应拦截
    customRequestError?: (error: Error) => void; // 自定义请求错误拦截
    customResponseError?: (error: Error) => void; // 自定义相应错误拦截
}

index.ts 文件内容需要根据项目自行修改外,其余文件无需修改

js

├── index.ts // 引用二次封装的asiox

使用案例

js
enum Api {
    roleList = '/manage/role/index'
}
export interface IRoleAuths {
    id:string;
    init_auth_id: string;
    init_auth_name: string;
    remark: string;
    role_name: string
}

// 角色-列表
export function api_manage_role_list() {
    return defHttp.get<Result<Record<'table_list', IRoleAuths[]>>>({url: Api.roleList});
}

index.ts 配置说明

ts
export const defHttp = createAxios({
    timeout: 10 * 1000,
    customTransform: {
        customRequest: custom_request,
        customRequestError: custom_request_error,
        customResponse: custom_response,
        customResponseError: custom_response_error
    },
    headers: {'Content-Type': ContentTypeEnum.JSON},
    requestOptions: {
        // 默认将prefix 添加到url
        joinPrefix: true,
        // 是否返回原生响应头 比如:需要获取响应头时使用该属性
        isReturnNativeResponse: false,
        // 消息提示类型
        errorMessageMode: 'message',
        // 接口地址
        apiUrl: import.meta.env.VITE_GLOB_API_URL,
        //  是否加入时间戳
        joinTime: true,
        // 是否在请求中加入环境参数
        joinEnv: true,
        // 忽略重复请求
        cancelToken: true
    }
});

transform 数据处理说明

类型定义,见 axiosTransform.ts 文件

js
export abstract class AxiosTransform {
  /**
   * @description: 请求之前处理配置
   */
  beforeRequestHook?: (config: AxiosRequestConfig, options: RequestOptions) => AxiosRequestConfig;
  /**
   * @description: 请求之前的拦截器
   */
  requestInterceptors?: (config: AxiosRequestConfig) => AxiosRequestConfig;

  /**
   * @description: 请求之后的拦截器
   */
  responseInterceptors?: (res: AxiosResponse<any>) => AxiosResponse<any>;

  /**
   * @description: 请求之前的拦截器错误处理
   */
  requestInterceptorsCatch?: (error: Error) => void;

  /**
   * @description: 请求之后的拦截器错误处理
   */
  responseInterceptorsCatch?: (error: Error) => void;
}

更改参数格式

项目接口默认为 Json 参数格式,即 headers: { 'Content-Type': ContentTypeEnum.FORM_URLENCODED },

如果需要更改为 json 格式,更改 headers 的 'Content-TypeContentTypeEnum.JSON 即可

多个接口地址

当项目中需要用到多个接口地址时, 可以在 src/utils/http/axios/index.ts 导出多个 axios 实例

ts
// 目前只导出一个默认实例,接口地址对应的是环境变量中的 VITE_GLOB_API_URL 接口地址
export const defHttp = createAxios();

// 需要有其他接口地址的可以在后面添加

// other api url
export const otherHttp = createAxios({
  requestOptions: {
    apiUrl: 'xxx',
  },
});

删除请求 URL 携带的时间戳参数

如果不需要 url 上面默认携带的时间戳参数 ?t=xxx

ts
export const defHttp = createAxios({
  requestOptions: {
    // 是否加入时间戳
    joinTime: false,
  },
});

删除请求 URL 携带的环境参数

如果不需要 url 上面默认携带的环境参数 ?env=xxx

ts
export const defHttp = createAxios({
  requestOptions: {
    // 是否加入时间戳
    joinEnv: false,
  },
});

Mock 服务

开发中

MIT Licensed