在 Vue 中,我们可以通过自定义指令和全局事件总线来实现全局 loading。
首先,我们可以自定义一个 v-loading 指令,用于控制全局 loading 的显示和隐藏。该指令可以在需要显示 loading 的组件中进行绑定,并接收一个布尔型的值作为参数,用于判断当前是否需要显示 loading。
// 定义 v-loading 指令
Vue.directive('loading', {
bind: function (el, binding) {
// 创建一个全局 div 元素并添加 loading 图标或者文字
const loading = document.createElement('div');
loading.innerHTML = '<i class="fa fa-spinner fa-spin"></i> loading...';
loading.className = 'loading';
// 根据指令的值来决定是否显示 loading
if (binding.value) {
el.disabled = true;
el.appendChild(loading);
}
},
update: function (el, binding) {
// 根据指令的新值来更新 loading 的状态
if (binding.value !== binding.oldValue) {
if (binding.value) {
el.disabled = true;
el.appendChild(loading);
} else {
el.disabled = false;
el.removeChild(loading);
}
}
}
});
接着,我们可以创建一个全局事件总线,用于在各个组件之间传递 loading 状态。全局事件总线可以使用 Vue 实例非响应式的 $emit 和 $on 方法来实现。在需要显示 loading 的地方可以通过 $emit 方法发送一个 showLoading 事件,而在需要隐藏 loading 的地方可以通过 $emit 方法发送一个 hideLoading 事件。
// 创建一个全局事件总线
const eventBus = new Vue();
// 监听 showLoading 事件,并显示 loading
eventBus.$on('showLoading', function () {
const loading = document.createElement('div');
loading.innerHTML = '<i class="fa fa-spinner fa-spin"></i> loading...';
loading.className = 'loading';
const app = document.querySelector('#app');
app.disabled = true;
app.appendChild(loading);
});
// 监听 hideLoading 事件,并隐藏 loading
eventBus.$on('hideLoading', function () {
const app = document.querySelector('#app');
const loading = document.querySelector('.loading');
if (loading) {
app.removeChild(loading);
}
app.disabled = false;
});
最后,在需要显示 loading 的地方,我们可以通过 $emit 方法发送一个 showLoading 事件来触发全局 loading 的显示。
// 在需要显示 loading 的地方发送 showLoading 事件
methods: {
fetchData: function () {
eventBus.$emit('showLoading');
axios.get('/api/data').then(response => {
// 处理数据
eventBus.$emit('hideLoading');
});
}
}
需要注意的是,在实际使用中,我们还需要为全局 loading 添加一些样式和动画,以提升用户体验。