Vue 单页应用 axios请求时 全局遮罩层设计

系统需求:

        在前端有请求时,并且请求还没有接收到响应时,需要显示个遮罩层,并显示加载状态,来屏蔽用户的操作;等所有请求都完成后,遮罩层消失,用户可以继续操作。

设计方案:

在主组件App.vue里,我们加一个遮罩层;

在store.state里加一个用来统计当前正在请求的个数 request_count ,这样我们就可全局来更新该变量,当有请求时 request_count + 1,当前有请求返回时request_count - 1 。

设计效果:

 

1、store/index.js

这里,我们把 request_count 定义在 $store.state.TMP 里,方便操作,全局的临时变量,我们项目开发要求约定都定义在TMP这里。

// 临时变量
        TMP: {
            do_close_page: false,       // 用来所有自定义标签页上的关闭按钮控制标签页的关闭,在App组件中添加Watch
            after_login_router: '/home', // 登录后跳转路由path
            request_count: 0, // 当前正在请求数
            loadingBar:false,
            session_id:'',
        },

TMP的更新方法

// 用来更新 TMP 里变量的方法
SET_TMP_VALUE(state, item) {
    state.TMP[item.name] = item.value;
},

2、App.vue

加一个遮罩层的样式通过 $store.state.TMP.request_count > 0 来控制显示

<div v-if="$store.state.TMP.request_count > 0">
    <div style="position: fixed; top: 0px; left: 0px; right: 0px; bottom: 0px; z-index: 99999; background: #eee; opacity: 0.5;"></div>
    <div style="font-size:50px; text-align:center; position: fixed; top: 0px; left: 0px; right: 0px; bottom: 0px; z-index: 99999;">
        <i class="fa fa-spinner fa-spin" style="margin-top:20%;"></i>
    </div>  
</div>

3、https.js

导入vuex配置文件

import store from './store/index.js'

axios

在请求拦截器方法里,更新请求个数统计

store.commit('SET_TMP_VALUE', {name:'request_count',value: store.state.TMP['request_count'] + 1})

在拦截响应器方法和拦截错误的里面分别添加,更新请求个数统计的代码

//返回状态判断(响应拦截器)
axios.interceptors.response.use((res) =>{
    ...
    store.commit('SET_TMP_VALUE', {name:'request_count',value: store.state.TMP['request_count'] - 1})
​
    ...
    ...
    
}, (error) => {
    ...
    store.commit('SET_TMP_VALUE', {name:'request_count',value: store.state.TMP['request_count'] - 1})
    ...
});

https 完整代码:

import axios from 'axios'
import qs from 'qs'
import store from './store/index.js'
import router from './router';
import Vue from 'vue'
import Cookies from 'js-cookie'
// 加载登录框插件
import loginbox from './plugins/loginbox/index.js'
Vue.use(loginbox)

import {Message} from 'view-design'; 

axios.defaults.timeout = 1200000;                        // 响应时间
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';        //配置请求头
// 在开发模式和生产模式环境变量文件中分别配置[VUE_APP_API_URL]参数值
//axios.defaults.baseURL = process.env.VUE_APP_API_URL;

//POST传参序列化(添加请求拦截器)
axios.interceptors.request.use((config) => {
    
    // session变了后,要重新加载页面
    if(store.state.TMP.session_id != '' && store.state.TMP.session_id != Cookies.get('S_YBS')){
        window.location =  window.location.href.replace(/#/g,"vue-router");
        return false;
    }
    
    config.headers['X-Requested-With'] = 'XMLHttpRequest'
    let regex = /.*XSRF-TOKEN=([^;.]*).*$/
    config.headers['X-XSRF-TOKEN'] = document.cookie.match(regex) === null ? null : document.cookie.match(regex)[1]

    store.commit('SET_TMP_VALUE', {name:'request_count',value: store.state.TMP['request_count'] + 1})
    return config;
},(error) =>{
    console.log('错误的传参');
    Message.error({content:'错误的传参', duration:4});
    return Promise.reject(error);
});

//返回状态判断(添加响应拦截器)
axios.interceptors.response.use((res) =>{

    store.commit('SET_TMP_VALUE', {name:'request_count',value: store.state.TMP['request_count'] - 1})

    //对响应数据做些事
    // 判断返回的数据中是否有token参数,如果有,那么要刷新store里的token
    if(res.data.token){
        store.commit('UPDATE_TOKEN', res.data.token);
    }
    
    // SESSION过期
    if (res.data.code == 1001) {
        // 清除cookies里的SESSION
        Cookies.remove('S_YBS');
        // 刷新页面
        window.location =  window.location.href.replace(/#/g,"vue-router");
        
    }else if(res.data.code == 1005){
        // 未登录,跳转到登录页
        window.location =  window.location.href.replace(/#/g,"vue-router");
    }
    if (res.data.err){
        console.log(res.data);
        Message.error({content:res.data.msg || '服务端程序错误', duration:4});
        return Promise.reject(res.data);
    }
    return res;
}, (error) => {
    store.commit('SET_TMP_VALUE', {name:'request_count',value: store.state.TMP['request_count'] - 1})
    console.log('请求失败');
    Message.error({content:'请求失败', duration:4});
    return Promise.reject(error);
});

//返回一个Promise(发送post请求)
export function fetchPost(url, params) {
    return new Promise((resolve, reject) => {
        axios.post(url, params)
            .then(response => {
                resolve(response);
            }, err => {
                reject(err);
            })
            .catch((error) => {
                reject(error)
            })
    })
}
返回一个Promise(发送get请求)
export function fetchGet(url, param) {
    return new Promise((resolve, reject) => {
        axios.get(url, {params: param})
            .then(response => {
                resolve(response)
            }, err => {
                reject(err)
            })
            .catch((error) => {
                reject(error)
            })
    })
}
// 设置axios请求的默认头信息
export function setHeaders(name, val){
    axios.defaults.headers.post[name] = val || "";
}
export default {
    fetchPost,
    fetchGet,
    setHeaders
}

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值