需求
vue脚手架搭建的h5工程,接口请求使用axios,每当请求发出,页面展现loading加载状态,请求完成或者请求失败,隐藏页面loading状态组件 组件采用了开源组件 vue-loading-spinner,GitHub地址为https://github.com/nguyenvanduocit/vue-loading-spinner 效果非常好的一款loading组件,可以根据实际项目自行编写loading组件或者npm install
完成效果
git clone https://github.com/nguyenvanduocit/vue-loading-spinner.git
下载到本地,或者
npm install --save vue-loading-spinner || yarn add vue-loading-spinner
找到node_modulers 里边对应的库文件,喜欢哪个loading组件,将其复制出来,封装如下 外层套一个frame 设置高宽各100%,内层元素居中,固定定位,背景色,以及z-index等等,凸显loading效果
/src/components/Loading/loading.vue
<template>
<div class="loading-frame">
<div v-bind:style="styles" class="spinner spinner--circle-9">
<div v-bind:style="innerStyles" class="spinner-inner">
<div class="loading spin-1">
<div class="loading spin-2">
<div class="loading spin-3">
<div class="loading spin-4">
<div class="loading spin-5"><div class="loading spin-6"></div></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
size: {
default: '40px'
}
},
computed: {
innerStyles() {
let size = parseInt(this.size);
return {
transform: 'scale(' + size / 120 + ')'
};
},
styles() {
return {
width: this.size,
height: this.size
};
}
}
};
</script>
<style lang="less" scoped>
.loading-frame {
width: 100%;
height: 100%;
position: fixed;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(255, 255, 255, 0.5);
z-index: 99999;
.spinner {
display: flex;
justify-content: center;
align-items: center;
* {
line-height: 0;
box-sizing: border-box;
}
}
.spinner-inner {
width: 120px;
height: 120px;
}
@keyframes circle-9-loading {
0% {
transform: rotate(0deg);
}
25% {
transform: rotate(160deg);
}
50% {
transform: rotate(0deg);
}
75% {
transform: rotate(160deg);
}
100% {
transform: rotate(0deg);
}
}
.loading {
background-color: transparent;
border-radius: 50%;
margin: 5px auto;
animation: circle-9-loading 5s infinite linear;
}
.spin-1 {
border: 5px solid #f7484e;
border-top: 5px solid transparent;
border-left: 5px solid transparent;
width: 120px;
height: 120px;
}
.spin-2 {
border: 5px solid #41b883;
border-top: 5px solid transparent;
border-left: 5px solid transparent;
width: 100px;
height: 100px;
animation-delay: 1s;
}
.spin-3 {
border: 5px solid #d2d947;
border-top: 5px solid transparent;
border-left: 5px solid transparent;
width: 80px;
height: 80px;
animation-delay: 1s;
}
.spin-4 {
border: 5px solid #f2a342;
border-top: 5px solid transparent;
border-left: 5px solid transparent;
width: 60px;
height: 60px;
animation-delay: 1s;
}
.spin-5 {
border: 5px solid #34495e;
border-top: 5px solid transparent;
border-left: 5px solid transparent;
width: 40px;
height: 40px;
animation-delay: 1s;
}
.spin-6 {
border: 5px solid #fff;
width: 20px;
height: 20px;
animation-delay: 1s;
}
}
</style>
src/store/index.ts 使用vuex方便全局控制loading显示与隐藏
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
LOADING: false
},
mutations: {
showLoading(state) {
state.LOADING = true;
},
hideLoading(state) {
state.LOADING = false;
}
}
});
src/App.vue 将loading组件挂载到工程根节点
<template>
<div id="app">
<Loading v-show="LOADING"></Loading>
...........//你的其他代码
</div>
<template>
import Loading from '@/components/Loading/loading.vue';
import { mapState } from 'vuex';
export default {
.....
components: {
Loading
},
computed: {
...mapState(['LOADING'])
},
......
}
src/plugins/axios.js 在封装好的axios中,利用axios的拦截器 实现 请求时提交store 显示 loading 请求失败或者完成 提交store 隐藏loading
"use strict";
import Vue from 'vue';
import axios from "axios";
import store from '@/store/index'
// Full config: https://github.com/axios/axios#request-config
// axios.defaults.baseURL = process.env.baseURL || process.env.apiUrl || '';
// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
let config = {
// baseURL: process.env.baseURL || process.env.apiUrl || ""
baseURL: "http://www.xxxxxx.com/shop/"
// baseURL: "/api"
// timeout: 60 * 1000, // Timeout
// withCredentials: true, // Check cross-site Access-Control
};
const _axios = axios.create(config);
_axios.interceptors.request.use(
function(config) {
// Do something before request is sent
store.commit('showLoading')
return config;
},
function(error) {
// Do something with request error
store.commit('hideLoading')
return Promise.reject(error);
}
);
// Add a response interceptor
_axios.interceptors.response.use(
function(response) {
// Do something with response data
store.commit('hideLoading')
return response;
},
function(error) {
// Do something with response error
return Promise.reject(error);
store.commit('hideLoading')
}
);
Plugin.install = function(Vue, options) {
Vue.axios = _axios;
global.axios = _axios;
Object.defineProperties(Vue.prototype, {
axios: {
get() {
return _axios;
}
},
$axios: {
get() {
return _axios;
}
},
});
};
Vue.use(Plugin)
export default Plugin;
exit()