记vue axios封装及全局遮罩处理

##在我们日常开发中,axios请求是必不可少的,甚至连vue作者尤雨溪都放弃了对vue-resource的维护,推荐我们使用axios库来进行前后端交互,而在开发过程中在每个单页面引入axios显然是比较麻烦的,一些功能实现起来也比较麻烦,比如说发出请求后显示一个遮罩,在请求成功后遮罩消失这一功能的实现,在axios请求统一管理之前,虽然在每个axios事件发送前后设置遮罩显示或隐藏状态是完全行得通的,但是相对来说比较繁琐,当我们请求比较多时,就会比较麻烦,因此今天分享一个本人刚实现的一个统一遮罩处理的方法。使用到的工具有 vant+vuex+axios。

一。 封装一个简单的遮罩

这里我是用的是vant组件库中的两个组件OverLay以及loading组件结合使用的

<template>
  <div>
    <van-overlay :show="show">
      <div class="wrapper" @click.stop>
        <van-loading type="spinner" />//这里是加载中图标
      </div>
    </van-overlay>
  </div>
</template>

<script>
export default {
    data(){
        return{
            show:this.show1
        }
    },
    props:["show1"],//通过父组件传过来的show1进行遮罩显示与隐藏 show1为布尔值
    watch:{
      "show1":function(n){
        this.show=n
      }
    },
    methods:{

    }
};
</script>

<style scoped>
.wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
}
</style>

之后将这个组件导入到app.vue中进行备用

二 封装axios

要实现这个功能,第一步也是最关键的一步就是对axios进行一个封装。我现在与src文件夹平级的位置创建一个request文件夹,内部包含两个js文件 分别是http.js(该文件的主要作用是创建一个axios实例,进行相关配置,将axios实例放在一个方法中抛出)。以及api.js(这部分功能是获取axios实例,将所有的接口路径写在这个文件中,抛出后在需要的页面进行引入。)
1.http.js
首先必须对axios进行安装

npm install axios

安装好后再http.js中进行导入

const axios = require("axios")
//这部分是为了判断当前环境是生产环境还是开发环境,因为设置了跨域代理,代理名是/api所以当是开发模式的时候,我这里将baseUrl设置为"/api",开发模式则获取当前环境的域名。
let baseUrl;
if(process.env.NODE_ENV==="development"){
    baseUrl = "/api"
}else{
    baseUrl = window.location.origin
}

接下来我们就通过axios.create()创建一个axios实例。

//这里的instance 我们可以把他直接理解为我们单页面引入的axios,不过这里我们可以自己配置一些东西 比如说baseUrl,responseType,
let instance = axios.create({
    baseURL: baseUrl,//会自动添加到我们请求的路径前面
    timeout: 0,//延时时间
    responseType: 'json'//规定响应内容默认的格式为json格式
})

接下来我们创建一个http()方法,通过http方法将我们创建好的instance结合promise来实现我们封装好的axios代码如下

function http(options, flag) {
    return new Promise((resolve, reject) => {
        resolve(instance(options))
    })
}
export default http  //将http方法抛出

到这里,最最简单的一个axios的封装就完成了,当然还有一些需要完善的地方,我们下一步要做的就是通过拦截器来对现在的步骤进行完善。
拦截器分为两种,分别是请求拦截器和响应拦截器,对应的也分别是我们发送请求之前以及获取到响应之前这两个阶段。(拦截器具体用处可移步axios文档)
首先我们要对响应拦截器进行处理,废话不多说,先贴代码

instance.interceptors.response.use(
            res => {
                 return res;
                   },
            err => {
                return Promise.reject(err)
                  }
        )

拦截器包含两个参数分别对应成功和失败时的信息,此外必须通过return将对应的信息进行返回,否则我们的请求会卡在这个地方,无法继续。
接下来考虑到我们的遮罩是全局任何页面都要适用,所以我是用vuex将需要传的值存储再state中,再与App.vue中的父子传值这里进行结合。

<template>
  <div id="app">
    <router-view/>
    <OverLay :show1="$store.state.show"></OverLay>//这里关键
    //vuex是响应式的
  </div>
</template>
<script>
import OverLay from "@/components/OverLay.vue"
export default {
  data(){
    return{
      show:true
    }
  },
  components:{
    OverLay
  }
}
</script>
<style lang="scss">

</style>

vuex中的代码比较简单

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    show:false,
    times:0  //判断当前同时共有多少个请求  所有请求结束后(即值为0)遮罩消失
  },
  mutations: {
    increment (state,n) {
      // 变更状态  n为布尔值 
      state.show=n
    },
    addTimes(state){
      state.times++  
      //该步骤放在响应发出之前
    },
    reduceTimes(state){
      state.times--
      //该步骤放在响应结束之后
    }
  },
  actions: {
  },
  modules: {
  }
})

此时再贴出http.js相关代码

import store from "../store/index.js" //引入store
function http(options, flag) {
    return new Promise((resolve, reject) => {
        instance.interceptors.request.use(res => {
            times++   
       //请求前拦截 每次++ 判断当前共有多少次请求     
       //并开启遮罩
            store.commit("increment", true)
            return res
        }, err => {
            return Promise.reject(err)
        })

        instance.interceptors.response.use(res => {
        //获取到响应前拦截 每次-- 当times为0时说明当前接口全部请求完毕        
        //关闭遮罩  即  store.commit("increment", false) 为false
            times--;
            console.log(times)
            if (times == 0) {
                store.commit("increment", false)
            }
            return res;
        },
            err => {
                times--;
                if (times == 0) {
                    store.commit("increment", false)
                }
                return Promise.reject(err)
            }
        )
        resolve(instance(options))
    })
}

至此我们全局遮罩已经实现

三 api.js使用方法

接下来再回到我们统一管理接口的文件api.js中

import http from "./http.js"
// import qs from "qs"
const getCountry = () => {
    return http({
        url: "/product/queryFromTrans.html",
        method: "post",
        params: { codeType: 'idtype' }
    })
}
const getProvince = () => {
    return http({
        method: "post",
        url: "/edor/initCities.html"
    })
}
//获取银行列表
const getEdorBank = () => {
    return http({
        method: 'post',
        url: '/product/getEdorBank.html',
    })
}
export {
    getCountry,getProvince,getEdorBank
}//这种导出方法引用时必须使用解构复制  

实例引用

import { getCountry} from "@request";//这里路径为自定义的  可以自行设置

在下萌新一枚,有不足之处欢迎各位留言指出

你可能感兴趣的:(记vue axios封装及全局遮罩处理)