简体   繁体   English

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

[英]How to display a "loading" animation while a lazy-loaded route component is being loaded?

I have split my app into multiple chunks with webpack's code splitting feature so that the entire application bundle isn't downloaded when the user visits my webpage.我已使用 webpack 的代码拆分功能将我的应用程序拆分为多个块,这样当用户访问我的网页时,就不会下载整个应用程序包。

The chunks that some routes require can be reasonably large and may take a noticeable amount of time to download.某些路由所需的块可能相当大,并且可能需要相当长的时间来下载。 This is fine, except the user is not aware that the page is actually loading when they click an internal link, so I need to somehow display a loading animation or something.这很好,除非用户在单击内部链接时不知道页面实际上正在加载,所以我需要以某种方式显示加载动画或其他东西。

My router is configured like this:我的路由器是这样配置的:

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

Advanced Async Components in the Vue.js guide shows how to display a particular "loading" component while the component is being resolved -- this is exactly what I need, however it also says: Vue.js 指南中的高级异步组件展示了如何在解析组件时显示特定的“加载”组件——这正是我所需要的,但它也说:

Note that when used as a route component in vue-router, these properties will be ignored because async components are resolved upfront before the route navigation happens.请注意,当在 vue-router 中用作路由组件时,这些属性将被忽略,因为异步组件是在路由导航发生之前预先解析的。

How can I achieve this in vue-router?如何在 vue-router 中实现这一点? If this is not possible, lazily-loaded components would be pretty much useless to me because it would provide a poor experience to the user.如果这是不可能的,那么延迟加载的组件对我来说几乎毫无用处,因为它会给用户带来糟糕的体验。

You can use navigation guards to activate/deactivate a loading state that shows/hides a loading component:您可以使用导航守卫来激活/停用显示/隐藏加载组件的加载状态:

If you would like to use something like "nprogress" you can do it like this:如果你想使用类似“nprogress”的东西,你可以这样做:

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

const router = new VueRouter({
  routes
})

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

Alternatively, if you want to show someting in-place:或者,如果您想就地展示一些东西:

http://jsfiddle.net/h4x8ebye/1/ 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
})

Then in the template:然后在模板中:

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

That could also be easily encapsulated in a very small component instead of using the $root component for the loading state.这也可以很容易地封装在一个非常小的组件中,而不是使用$root组件来加载状态。

For what it's worth, I'll share what I ended up doing for my situation.对于它的价值,我将分享我最终为我的情况所做的事情。

I'm using Vuex so it was easy to create an app-wide "loading" state which any component can access, but you can use whatever mechanism you want to share this state.我正在使用 Vuex,因此很容易创建任何组件都可以访问的应用程序范围的“加载”状态,但您可以使用任何想要共享此状态的机制。

Simplified, it works like this:简化后,它的工作原理如下:

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')),
    },
  ];
}

So all I have to do is wrap every () => import() by my load() function which takes care of setting the loading state.所以我所要做的就是用我的load()函数包装每个() => import() ,该函数负责设置加载状态。 Loading is determined by observing the promise directly instead of relying on router-specific before/after hooks.加载是通过直接观察 Promise 来确定的,而不是依赖于特定于路由器的 before/after 钩子。

you can use this code for gobel route in one project of vuejs您可以在 vuejs 的一个项目中将此代码用于 gobel 路由

const router = new Router({
  routes: [
      { path: '/', name: 'home', component: Home },
      { path: '/about', name: 'about', component: About }
  ]
})

router.beforeResolve((to, from, next) => {
  // If this isn't an initial page load.
  if (to.name) {
      // Start the route progress bar.
      NProgress.start()
  }
  next()
})

router.afterEach((to, from) => {
  // Complete the animation of the route progress bar.
  NProgress.done()
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 有没有办法检查延迟加载的组件(使用 React.Lazy)是否已完成加载? - Is there a way to check if a lazy-loaded component (with React.Lazy) has finished loading? Vue路由器仅显示一次延迟加载的路由组件 - Vue router shows lazy-loaded route components only once 组件无法从延迟加载的模块中找到提供程序 - component can't find provider from lazy-loaded module 来自延迟加载组件的 Angular 2+ 访问/更改变量 - Angular 2+ Access/Change Variable from Lazy-Loaded component Vue 路由器如何在页面加载时获取延迟加载模块的当前路由路径? - How can Vue router get current route path of lazy-loaded modules on page load? 如何自定义延迟加载页面之间共享的 React 组件的样式? - How can I customize the style of a React component shared between lazy-loaded pages? AngularJS-内容加载时如何显示消息“ Loading…”? - AngularJS - How to display message “Loading…” while the content is being loaded? 如何在加载模型时在Ember中显示加载模板? - How to display a loading template in Ember while model is being loaded? 从延迟加载的文件延迟加载时发生错误-angular.js - Error when lazy-loading from a lazy-loaded file - angular.js 带有延迟加载图像的结构化数据? - Structured Data with Lazy-Loaded images?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM