Vue编程如何实现全局loading?

190 阅读1分钟

在 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 添加一些样式和动画,以提升用户体验。