美文网首页
Vue3.2+Vite2.x+Typescript项目进阶搭建-

Vue3.2+Vite2.x+Typescript项目进阶搭建-

作者: 无我_无他_有你 | 来源:发表于2022-05-20 14:41 被阅读0次

    axios模块的功能主体:对发起的请求做处理,对响应的请求做处理,对请求方式进行封装,对请求进行管理等等
    vuex搭建(官方文档
    引入依赖

    #axios依赖
    npm install axios --save
    
    #qs 依赖 (对请求传的参数转json字符串处理工具)
    npm install qs --save
    

    src下创建目录axios,axios目录下创建request.ts文件,内容如下(仅作参考)

    import { message } from './../utils/resetMessage';
    //引入 axios
    import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
    import qs from "qs";
    import localStorageUtil from "/@utils/localStorageUtil";
    import loadingUtil from "/@utils/loading";
    import messageUtil from "/@utils/messageUtil";
    import { ACCOUNT_SERVER } from "/@assets/constant/domain-name";
    import router from "../router";
    import { userStore } from "/@store/index";
    
    const BASE_URL = "/api/" + ACCOUNT_SERVER;
    // //允许跨域携带cookie信息 改配置与后端保持一致
    axios.defaults.withCredentials = true;
    // 设置重新请求次数
    axios.defaults.retry = 10;
    // 设置请求延时
    axios.defaults.retryDelay = 1000;
    
    // 接口类型和方法
    interface BaseType {
      baseURL: string;
      getConfigParams(): any;
      interceptors(instance: AxiosInstance, url: string | number | undefined): any;
      request(options: AxiosRequestConfig): any;
    }
    
    interface AxiosRequestType {
      baseURL?: string;
      url?: string | undefined;
      data?: any;
      params?: any;
      method?: string;
      headers?: any;
      timeout?: number;
      value?: any;
      cancelToken?: any;
    }
    
    // 取消重复请求
    const CancelToken = axios.CancelToken;
    // 用于存储每个请求的取消函数以及对应标识
    let sources: any = [];
    // 取消函数
    let removeSource = (config: any) => {
      for (let item in sources) {
        if (sources[item].cancelFunction === config.url + "&" + config.method) {
          sources[item].cancel("已取消重复请求,请勿重复请求");
          sources.splice(item, 1);
        }
      }
    };
    let baseURL = import.meta.env.BASE_URL;
    console.log("当前环境的基础路径为:" + baseURL);
    
    class AxiosHttpRequest implements BaseType {
      baseURL: string;
      timeout: number;
      constructor(baseURL: string, timeout: number) {
        this.baseURL = import.meta.env.BASE_URL;
        this.timeout = 10000;
      }
      // 配置参数
      getConfigParams() {
        const config = {
          baseURL: this.baseURL,
          timeout: this.timeout,
          headers: {},
        };
        return config;
      }
      // 拦截设置
      interceptors(config: AxiosInstance, url: string | number | undefined) {
        // 请求拦截
        config.interceptors.request.use(
          (config: AxiosRequestType) => {
            // 断网提示 李兰器不在线提示用户网络有问题
            if (!navigator.onLine) {
              messageUtil.warn("您的网络故障,请检查!");
              return;
            }
            // 取消重复请求
            removeSource(config);
            config.cancelToken = new CancelToken((c) => {
              // 将取消函数存起来
              sources.push({
                cancelFunction: config.url + "&" + config.method,
                cancel: c,
              });
            });
            // 添加全局的loading..
            loadingUtil.show();
            //全局参数统一处理
            if (config.method === "post") {
              config.data = qs.stringify({ ...config.data });
            } else {
              config.params = { ...config.params };
            }
            // 请求头携带token
            // get请求映射params参数
            if (config.method === "get" && config.params) {
              let url = config.url + "?";
              for (const propName of Object.keys(config.params)) {
                const value = config.params[propName];
                var part = encodeURIComponent(propName) + "=";
                if (value !== null && typeof value !== "undefined") {
                  if (typeof value === "object") {
                    for (const key of Object.keys(value)) {
                      let params = propName + "[" + key + "]";
                      var subPart = encodeURIComponent(params) + "=";
                      url += subPart + encodeURIComponent(value[key]) + "&";
                    }
                  } else {
                    url += part + encodeURIComponent(value) + "&";
                  }
                }
              }
              url = url.slice(0, -1);
              config.params = {};
              config.url = url;
            }
    
            //2.获取时间戳,精确到秒
            let getTimestamp = Date.now().toString().substring(0, 10);
            let url = config.url;
            if (url) {
              let indexOf = url.indexOf("?");
              if (indexOf > -1) {
                config.url = config.url + "&timestamp=" + getTimestamp;
              } else {
                config.url = config.url + "?timestamp=" + getTimestamp;
              }
            }
            if (config.headers) {
              console.log("获取pinia中的token:" + userStore().getToken);
              //3.添加请求头token
              if (userStore().token && userStore().getToken != "") {
                config.headers["Authentication"] = userStore().getToken;
              } else {
                //token 不存在跳转到登录页
                router.replace("/login");
              }
            }
            return config;
          },
          (error: any) => {
            return Promise.reject(error);
          }
        );
    
        // 响应拦截
        config.interceptors.response.use(
          (res: any) => {
            debugger;
            // 取消重复请求
            removeSource(res.config);
            loadingUtil.hide();
            // 获取错误信息
            if (res.data.body) {
              let errCode = res.data.body.errCode;
              switch (errCode) {
                //token失效重新获取token
                case "A0225":
                  http
                    .get({
                      url: BASE_URL + "/token/refreshToken",
                    })
                    .then((res: any) => {
                      localStorageUtil.set("accessToken", res.data);
                      //重新发送请求 TODO
                      var config = res.config;
                      return axios(config);
                    });
                  break;
                case "A0313":
                   messageUtil.error("权限不足,请联系管理员");
                  return Promise.reject(res);
              }
            } else {
              return Promise.resolve(res);
            }
          },
          (error: any) => {
            debugger;
            let msg: string;
            if (error.response) {
              let code: number = error.response.status;
              switch (code) {
                case 400:
                  msg = "错误请求";
                  break;
                case 401:
                  msg = "认证信息已失效";
                  router.push("/login");
                  break;
                case 403:
                  msg = "客户端非法请求";
                  break;
                case 404:
                  msg = "访问资源不存在";
                  break;
                case 405:
                  msg = "请求方式错误";
                  break;
                case 500:
                  msg = "服务器内部异常";
                  break;
                case 503:
                  msg = "服务不可用";
                  break;
                case 504:
                  msg = "网络超时";
                  break;
                case 505:
                  msg = "http版本不支持该请求";
                  break;
                default:
                  msg = "未知错误,请联系管理员";
                  break;
              }
            } else {
              msg = error.message;
              if (msg == "Network Error") {
                msg = "后端接口连接异常";
              } else if (msg.includes("timeout")) {
                msg = "系统接口请求超时";
              } else if (msg.includes("Request failed with status code")) {
                msg = "系统接口" + msg.substring(msg.length - 3) + "异常";
              }
            }
            loadingUtil.hide();
             messageUtil.error(msg);
            return Promise.reject(error);
          }
        );
      }
    
      /**
       * 外部调用方法
       * @param options axios请求参数
       * @returns 实例
       */
      request(options: AxiosRequestConfig) {
        const instance = axios.create();
        options = Object.assign(this.getConfigParams(), options);
        this.interceptors(instance, options.url);
        return instance(options);
      }
    
      get<T>(config: AxiosRequestConfig) {
        return this.request({ ...config, method: "GET" });
      }
      post<T>(config: AxiosRequestConfig) {
        return this.request({ ...config, method: "POST" });
      }
      put<T>(config: AxiosRequestConfig) {
        return this.request({ ...config, method: "PUT" });
      }
      delete<T>(config: AxiosRequestConfig) {
        return this.request({ ...config, method: "DELETE" });
      }
      patch<T>(config: AxiosRequestConfig) {
        return this.request({ ...config, method: "PATCH" });
      }
    }
    
    // 实例化请求类
    const http = new AxiosHttpRequest(baseURL, 3000);
    
    export default http;
    
    

    该过程是对请求动作,处理内容主要包括以下几方面
    1.请求方式封装
    2.重复请求过滤
    3.请求头添加token
    4.请求参数统一处理
    5.请求拦截,对不需要权限的请求直接放行
    6.对请求响应结果处理
    7.请求重试
    8.结合状态管理框架(vuex,pinia)处理用户权限信息等

    api处理

    src下创建目录 api 该目录用户存放调用接口方法,方便管理,文件内容示例:

    import http from "../axios/request";
    import globalConst from "/@constants/domain-name";
    
    export function login(data: any) {
      return http.post({
        url: globalConst.account_server + "/user/login",
        data,
      });
    }
    
    export function logout(data: any) {
      return http.post({
        url: globalConst.account_server + "/user/logout",
        data: data,
      });
    }
    
    export function findById(id: number) {
      return http.get({
        url: globalConst.account_server + "/user/findUserById/",
        params: { id: id },
      });
    }
    
    export function getVerificationCode() {
      return http.get({
        url: globalConst.account_server + "/user/verifyCode",
        responseType: "blob",
      });
    }
    
    export function getUserMenuList() {
      return http.get({
        url: "/api/" + globalConst.auth_server + "/menu/tree",
      });
    }
    
    

    相关文章

      网友评论

          本文标题:Vue3.2+Vite2.x+Typescript项目进阶搭建-

          本文链接:https://www.haomeiwen.com/subject/unvgsrtx.html