vue实现loading插件
Vue 实现 Loading 插件的方法
使用全局组件与状态管理
创建一个全局的 Loading 组件,通过 Vuex 或 Pinia 管理其显示状态。在需要的地方通过状态控制显示或隐藏。
Loading 组件示例:
<template>
<div v-if="isLoading" class="loading-overlay">
<div class="loading-spinner"></div>
</div>
</template>
<script>
export default {
computed: {
isLoading() {
return this.$store.state.isLoading;
}
}
};
</script>
<style>
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
}
.loading-spinner {
border: 4px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top: 4px solid #fff;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
在 Vuex 中管理状态:
const store = new Vuex.Store({
state: {
isLoading: false
},
mutations: {
setLoading(state, isLoading) {
state.isLoading = isLoading;
}
}
});
使用插件形式封装
将 Loading 功能封装为 Vue 插件,便于全局调用。
插件实现:
const LoadingPlugin = {
install(Vue) {
const LoadingComponent = Vue.extend({
template: '<div v-if="show" class="loading-overlay"><div class="loading-spinner"></div></div>',
data() {
return { show: false };
}
});
let loadingInstance = null;
Vue.prototype.$loading = {
show() {
if (!loadingInstance) {
loadingInstance = new LoadingComponent({
el: document.createElement('div')
});
document.body.appendChild(loadingInstance.$el);
}
loadingInstance.show = true;
},
hide() {
if (loadingInstance) {
loadingInstance.show = false;
}
}
};
}
};
Vue.use(LoadingPlugin);
调用方式:
this.$loading.show(); // 显示 loading
this.$loading.hide(); // 隐藏 loading
使用指令实现局部 Loading
通过自定义指令在元素上实现局部 Loading 效果。
指令实现:
Vue.directive('loading', {
bind(el, binding) {
const loadingDiv = document.createElement('div');
loadingDiv.className = 'loading-spinner';
el.style.position = 'relative';
loadingDiv.style.position = 'absolute';
loadingDiv.style.top = '50%';
loadingDiv.style.left = '50%';
loadingDiv.style.transform = 'translate(-50%, -50%)';
el.loadingElement = loadingDiv;
if (binding.value) {
el.appendChild(loadingDiv);
}
},
update(el, binding) {
if (binding.value) {
el.appendChild(el.loadingElement);
} else {
if (el.contains(el.loadingElement)) {
el.removeChild(el.loadingElement);
}
}
}
});
使用方式:
<template>
<div v-loading="isLoading"></div>
</template>
结合异步请求拦截器
在 axios 拦截器中自动控制 Loading 状态。
拦截器示例:
let loadingCount = 0;
axios.interceptors.request.use(config => {
loadingCount++;
if (loadingCount === 1) {
store.commit('setLoading', true);
}
return config;
});
axios.interceptors.response.use(
response => {
loadingCount--;
if (loadingCount === 0) {
store.commit('setLoading', false);
}
return response;
},
error => {
loadingCount--;
if (loadingCount === 0) {
store.commit('setLoading', false);
}
return Promise.reject(error);
}
);
以上方法可根据项目需求选择或组合使用,实现灵活可控的 Loading 效果。







