需求

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()

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐