VUE自定义通用接口配置

常用axios安装和引用

  • 安装axios

    npm install axios  --save-dev
    npm install vue-axios --save-dev //结合vue-axios使用
    

axios中文文档

  • 引用

    //在index.html中引用
    <script src="https://cdn.bootcss.com/vue/2.5.2/vue.js"></script>
    <script src="https://cdn.bootcss.com/vuex/3.1.0/vuex.js"></script>
    <script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.js"></script>
    <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
    <script src="/static/js/jsonlint.js"></script>  //转long类型 转义JSON
    
    
    //在入口文件main.js引入
    import axios from 'axios'
    import VueAxios from 'vue-axios'
    //依靠vue-axios插件式引用
    Vue.use(VueAxios,axios);
    this.axios.get('api/getNewsList').then((response)=>{}).catch((response)=>{})
    
    //或挂载在Vue的原型上
    Vue.prototype.$ajax= axios
    this.$ajax.get('api/getNewsList').then((response)=>{}).catch((response)=>{})
    

通用配置详细记录

  • 在根目录src下自建api文件夹(个人习惯:把统一配置单独存放)

  • 在api文件下分别新建api.js和http.js

  • 在http.js下详细配置接口

    //http.js
    import axios from 'axios';
    import Crypto from './crypto';//加密
    import Router from '../../router/index';//导入路由
    import store from "../../store" //引入vuex
    //用于存放开发、测试、正式地址,可写多个,按需使用
    let baseUrl = "http://192.168.0.156:155";
    //或在全局的 axios 设置默认值
    axios.defaults.timeout = 6000;
    //修改响应数据
    axios.defaults.transformResponse = [
      function (res) {
          //此处用于识别换行符
          res = res.replace(/%n|\\n/gm, '<br />')
         //转义emoji表情
        var reg = /\\uD83C[\\uDF00-\\uDFFF]|\\uD83D[\\uDC00-\\uDE4F]/g;
        if (reg.test(res)) {
          res = res.replace(/\\/g, "%");
            // res = res.replace(/%n/g, "");
          res = unescape(res);//unescape解码字符串,escape编码字符串使计算机上读取该字符串
      }
        // 转换long类型为string 防止溢出;
          return jsonlint.parse(res);
      }
    ]
    //请求头配置(依据实际项目配置)
    export let headersConfig = {
        'sign': escape(Crypto.encryptByDES("jU7dDd0+68" + new Date().getTime(), "k8!MZms@")),//根据项目配置加密
        'ver': '1.0.6',
        'os': 'web',
        'Content-Type': 'application/json'
    };
    //创建实例
    let MainAxios = axios.create({
      baseURL: baseUrl,
      timeout: 6000,//设置超时
    });
    /**
     * get方法,对应get请求
       * url [请求的url地址]
       * params [请求时携带的参数]
     **/
    export function Get(url, params) {
      if (!params) {
        params = ""
    }
    return new Promise(function (resolve, reject) {
      MainAxios.get(url, {
        headers: headersConfig,
        params: params //axios的get请求传参使用params
      })
      .then(res => {
        resolve(res.data);
      })
      .catch(err => {
        reject(err.data)
      })
    })
    }
    
    /**
     * post方法,对应post请求
     * @param {String} url [请求的url地址]
     * @param {Object} params [请求时携带的参数]
     */
    export function Post(url, params) {
      return new Promise((resolve, reject) => {
        if (!params) {
          params = {}
      }
      MainAxios.post(url, params, {
        headers: headersConfig
      }).then(res => {
        resolve(res.data);
      })
      .catch(err => {
        reject(err.data)
      })
    });
    }
    
     /**
      * 解决请求重复提交并进一步封装全系统重复请求拦截
     */  
    let pending = []; //声明一个数组用于存储每个ajax请求的取消函数和ajax标识
    let cancelToken = axios.CancelToken; //指定用于取消请求的 cancel token
    let removeRepeatUrl = (ever) => { //声明一个方法
      for(let p in pending){
          if(pending[p].u === ever.url + '&' + ever.method) { //当前请求在数组中存在时执行函数体
              pending[p].f(); //执行取消操作
              pending.splice(p, 1); //把这条记录从数组中移除
          }
      }
    }
    
    // 请求拦截器
    MainAxios.interceptors.request.use(config => {
       //在一个ajax发送前执行一下取消操作
       removeRepeatUrl(config); 
       config.cancelToken = new cancelToken((c)=>{
           // 自定义唯一标识 f:方法简写 c:内置cancel方法
          pending.push({ u: config.url + '&' + config.method, f: c });  
       });
    
      //根据项目而定,配置token,一般在登录注册接口本地存储token
      let token = localStorage.getItem('token');
      if (token) {
          config.headers['Authorization'] = token;
      }
       return config
     }, err => {
         return Promise.reject(err)
    })
    
    // 响应拦截器
    MainAxios.interceptors.response.use(response=> {
      removeRepeatUrl(response.config);  //在一个ajax响应后再执行一下取消操作,把已经完成的请求从pending中移除
       //设置找不到默认页面
       if (response.data.status == 50001) {
        Router.push({
          path: "/NothingFind",
          replace: true,
          query: {
            title: Router.history.current.meta.title //用于设置找不到页面标题
          },
    });
      return Promise.resolve(response);
    }, err => {
      // 服务器状态码不是200的情况
      if (error.response.status) {
      switch (error.response.status) {
      // 401: 未登录
      // 未登录则跳转登录页面,并携带当前页面的路径
      // 在登录成功后返回当前页面,这一步需要在登录页操作。
      case 401:
        store.commit('del_token');
        setTimeout(() => {
          // 如果有多个接口出现401 保证只执行一次弹出登录
          if (!Router.history.current.query.lastPage) {
            Router.push({
              path: "/Login",
              replace: true,
              query: {
                lastPage: Router.history.current.path,
                query: JSON.stringify(Router.history.current.query)
              } // 将跳转的路由path作为参数,登录成功后跳转到该路由
            });
          }
        }, 600);
        break;
      // 403 token过期
      // 登录过期对用户进行提示
      // 清除本地token和清空vuex中token对象
      // 跳转登录页面
      case 403:
        // 清除token
        store.commit('del_token');
        // 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
        setTimeout(() => {
          // 如果有多个接口出现403 保证只执行一次弹出登录
          if (!Router.history.current.query.lastPage) {
            Router.push({
              path: "/Login",
              replace: true,
              query: {
                lastPage: Router.history.current.path,
                query: JSON.stringify(Router.history.current.query)
              } // 将跳转的路由path作为参数,登录成功后跳转到该路由
            });
          }
        }, 600);
        break;
      // 404请求不存在
      case 404:
        console.log('网络请求不存在')
        break;
      // 其他错误,直接抛出错误提示
      default:
        console.log(error.response.data.message)
    }
      return Promise.reject(error.response);
    }
      return Promise.reject(error)
    })
    
  • 附录store关于token删除写法

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex);
    export default Vue.prototype.$store = new Vuex.Store({
      state: {
        token: "",
      },
      getters:{},
      mutations: {
            //存储token
            set_token(state, token) {
                  state.token = token;
                  localStorage.token = token
             },
            //删除token
            del_token(state) {
              state.token = '';
              localStorage.removeItem('token')
          }
      }  
    })
    
  • 在api.js下配置接口

    import {
        Get,
        Post
    } from './http'
    
    //例如 get post请求
    let getVerificationCode = function (params) {
      return Get('/v1/usercenter/personalData/getCode', params)
    }
    let Login = function (params) {
      return Post('/v2/system/auth/loginBySMS', params)
    }
    
    export const dataApi = {
       getVerificationCode: getVerificationCode,
       Login: Login
    };
    
  • 在入口文件main.js中挂载

    import Vue from 'vue'
    import {dataApi} from '@/api/api';
    // 全局挂载Api
    Vue.prototype.$Api = {
        dataApi: dataApi,
    };
    
  • 具体使用

    //formData传参
    this.$Api.dataApi
        .Login(formData)
        .then(res => {
          console.log(res )
       })
       .catch(err => {
          console.log(err)
       });
    
图解
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,473评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,229评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,570评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,427评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,335评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,737评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,392评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,693评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,730评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,512评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,349评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,750评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,017评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,290评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,706评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,904评论 2 335

推荐阅读更多精彩内容