之前介绍过一篇《typescript 配置 axios》。那个版本用了class语法,本次介绍 vue3.0 普通的写法,最后用 eggjs 测试通过登录接口。

./src/api 目录下需要 api.tsstatus.tstype.ts 三个文件。

├── src
│   ├── api
│   │   ├── api.ts
│   │   ├── status.ts
│   │   └── type.ts

./src/api/api.ts

import axios, {AxiosInstance, AxiosRequestConfig, AxiosResponse} from 'axios';
import qs from 'qs'
import { showMessage } from "./status";
import { ElMessage } from 'element-plus'
import { IResponse, ILogin } from './type';

let axiosInstance:AxiosInstance = axios.create({
  baseURL: process.env.VUE_APP_BASE_URL + "/api/v1/",
  headers: {
    Accept: "application/json",
    "Content-Type": "application/x-www-form-urlencoded"
  },
  transformRequest: [
    function(data) {
      //由于使用的 form-data传数据所以要格式化
      delete data.Authorization;
      data = qs.stringify(data);
      return data;
    }
  ]
});

// axios实例拦截响应
axiosInstance.interceptors.response.use(
  (response: AxiosResponse) => {
    if (response.headers.authorization) {
      localStorage.setItem('app_token', response.headers.authorization);
    } else {
      if (response.data && response.data.token) {
        localStorage.setItem('app_token', response.data.token);
      }
    }

    if (response.status === 200) {
      return response;
    } else {
      showMessage(response.status);
      return response;
    }
  },
  // 请求失败
  (error: any) => {
    const {response} = error;
    if (response) {
      // 请求已发出,但是不在2xx的范围
      showMessage(response.status);
      return Promise.reject(response.data);
    } else {
      ElMessage.warning('网络连接异常,请稍后再试!');
    }
  }
);

// axios实例拦截请求
axiosInstance.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    // const { user } = store.state
    // if (token) {
    //   config.headers.Authorization = `Bearer ${token}`
    // }
    return config;
  },
  (error:any) => {
    return Promise.reject(error);
  }
) 

/**
 * @description: 用户登录
 * @params {ILogin} params
 * @return {Promise}
 */
export const login = (params: ILogin): Promise<IResponse> => {
  return axiosInstance.post('user/login',params).then(res => res.data);
};
  • 整体还是创建实例的方式,通过给实例添加请求和响应拦截,做对应处理。
  • axios.createtransformRequest 配置,先删除参数中的 Authorization, 再通过 qs 依赖转换了参数的形式(将对象字面量转化成 Form Data 格式)。
  • 响应拦截中做了对 token 的处理
  • 请求拦截中这请求头部 header 中给 Authorization 添加 token,根据具体业务需求修改。
  • 本文件创建一个登录接口 login 用来测试 eggjs 提供的接口。

./src/api/status.ts

export const showMessage = (status:number|string) : string => {
  let message:string = "";
  switch (status) {
    case 400:
      message = "请求错误(400)";
      break;
    case 401:
      message = "未授权,请重新登录(401)";
      break;
    case 403:
      message = "拒绝访问(403)";
      break;
    case 404:
      message = "请求出错(404)";
      break;
    case 408:
      message = "请求超时(408)";
      break;
    case 500:
      message = "服务器错误(500)";
      break;
    case 501:
      message = "服务未实现(501)";
      break;
    case 502:
      message = "网络错误(502)";
      break;
    case 503:
      message = "服务不可用(503)";
      break;
    case 504:
      message = "网络超时(504)";
      break;
    case 505:
      message = "HTTP版本不受支持(505)";
      break;
    default:
      message = `连接出错(${status})!`;
  }
  return `${message},请检查网络或联系管理员!`;
};
  • status.ts 返回相应状态对应的信息文字。

./src/api/type.ts

// 返回res.data的interface
export interface IResponse {
  code: number | string;
  data: any;
  msg: string;
}

/**用户登录 */
export interface ILogin {
  /** 账户名称 */
  username: string;
  /** 账户密码 */
  password: string;
}
  • type.ts 集中定义各种 api 相关的接口。如果以后接口过多,这个文件可能会很臃肿,如果哪位大神还有其他优化文件夹目录方式,欢迎一起讨论。

前端测试接口的话,和上次一样还是用 /src/views/Home.vue

import { defineComponent, onMounted } from 'vue';
import { login } from '@/api/api';
export default defineComponent({
  name: 'Home',
  setup() {
  	onMounted(()=>{
      login({
  		username:'admin',
  		password:'123456'
  	  });
  	})
  }
});

最后是调用 eggjs 提供的接口,关于 eggjs 这里不做过多介绍,参照官方文档写个demo也不算复杂。

  • eggjslogin 接口地址是 http://localhost:7001/api/v1/user/login
  • 我的 env 配置文件中的 VUE_APP_BASE_URLhttp://0.0.0.0:7001。 这样可以调用接口。

接口返回的数据通过 ./src/api/api.ts 处理的返回结果(res.data)如下:

{
  "code": 200,
  "msg": "登录成功",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InNvbmljIiwiaWF0IjoxNjE4OTc0NDQzfQ.XtKLR2_AHFq0r5we71V7BWVtXvQLeYu2OGYv-w8iZEM"
  }
}
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐