如何在加载延迟加载的路由组件时显示“加载”动画?

新手上路,请多包涵

我已使用 webpack 的代码拆分功能将我的应用程序拆分为多个块,以便在用户访问我的网页时不会下载整个应用程序包。

某些路由所需的块可能相当大,并且可能需要花费大量时间才能下载。这很好,除非用户在单击内部链接时不知道页面实际上正在加载,因此我需要以某种方式显示加载动画或其他内容。

我的路由器是这样配置的:

 [
  {
    path: '/',
    component: () => import(/* webpackChunkName: 'landing' */ './landing.vue'),
  },
  {
    path: '/foo',
    component: () => import(/* webpackChunkName: 'main' */ './foo.vue'),
  },
  {
    path: '/bar',
    component: () => import(/* webpackChunkName: 'main' */ './bar.vue'),
  },
]

Vue.js 指南中的 高级异步组件 展示了如何在解析组件时显示特定的“正在加载”组件——这正是我所需要的,但它也说:

请注意,当在 vue-router 中用作路由组件时,这些属性将被忽略,因为异步组件会在路由导航发生之前预先解析。

我怎样才能在 vue-router 中实现这个?如果这不可能,那么延迟加载的组件对我来说几乎毫无用处,因为它会给用户带来糟糕的体验。

原文由 Decade Moon 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 789
2 个回答

您可以使用导航守卫来激活/停用显示/隐藏加载组件的加载状态:

如果你想使用像“nprogress”这样的东西,你可以这样做:

http://jsfiddle.net/xgrjzsup/2669/

 const router = new VueRouter({
  routes
})

router.beforeEach((to, from, next) => {
  NProgress.start()
  next()
})
router.afterEach(() => {
  NProgress.done()
})

或者,如果你想就地展示一些东西:

http://jsfiddle.net/h4x8ebye/1/

 Vue.component('loading',{ template: '<div>Loading!</div>'})

const router = new VueRouter({
  routes
})

const app = new Vue({
  data: { loading: false },
  router
}).$mount('#app')

router.beforeEach((to, from, next) => {
  app.loading = true
    next()
})

router.afterEach(() => {
  setTimeout(() => app.loading = false, 1500) // timeout for demo purposes
})

然后在模板中:

 <loading v-if="$root.loading"></loading>
  <router-view v-else></router-view>

这也可以很容易地封装在一个非常小的组件中,而不是使用 $root 组件来加载状态。

原文由 Linus Borg 发布,翻译遵循 CC BY-SA 4.0 许可协议

对于它的价值,我将分享我最终为我的情况所做的事情。

我正在使用 Vuex,因此很容易创建任何组件都可以访问的应用程序范围的“正在加载”状态,但是您可以使用任何您想要共享此状态的机制。

简化后,它的工作原理如下:

 function componentLoader(store, fn) {
  return () => {
    // (Vuex) Loading begins now
    store.commit('LOADING_BAR_TASK_BEGIN');

    // (Vuex) Call when loading is done
    const done = () => store.commit('LOADING_BAR_TASK_END');

    const promise = fn();
    promise.then(done, done);
    return promise;
  };
}

function createRoutes(store) {
  const load = fn => componentLoader(store, fn);

  return [
    {
      path: '/foo',
      component: load(() => import('./components/foo.vue')),
    },
    {
      path: '/bar',
      component: load(() => import('./components/bar.vue')),
    },
  ];
}

所以我所要做的就是用我的 load() 函数包装每个 () => import() 负责设置加载状态的函数。加载是通过直接观察承诺来确定的,而不是依赖于路由器特定的前/后挂钩。

原文由 Decade Moon 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题