美文网首页
VUE自定义通用接口配置

VUE自定义通用接口配置

作者: 小碗吃不了 | 来源:发表于2019-12-21 17:20 被阅读0次

    常用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)
         });
      
    图解

    相关文章

      网友评论

          本文标题:VUE自定义通用接口配置

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