Vue Router 懒加载组件状态不支持loading属性

vue-router

#1

更新:Github Issue 上有人提了这个问题,目前解决方法就是添加一个异步组件:https://github.com/vuejs/vue-router/pull/2140


Vue Router 懒加载过程中需要显示loading状态,大部分的解决方案是使用beforeEach和afterEach的函数。

看到官网上异步组件的介绍,异步组件支持一个loading的属性,这个属性主要用于异步组件的定义。

特别是最后一句:

注意如果你希望在 Vue Router 的路由组件中使用上述语法的话,你必须使用 Vue Router 2.4.0+ 版本。

我的问题是Vue Router是否支持以上的写法呢?router-view的懒加载显示loading状态是很常见的场景。

经过测试,Vue Router不支持loading状态的显示,只支持异步加载。代码如下

JS Bin on jsbin.com

var syncComponent = { template: '<div>Sync Component</div>' }

var asyncComponent = function () {
  return new Promise(function (resolve) {
    setTimeout(function() {
      resolve({ template: '<div>Async Component</div>' })
    }, 1000)
  })
}

var LoadingComponent = { template: '<h1>Loading...</h1>' }

var router = new VueRouter({
  routes: [
    { path: '/', redirect: '/syncComponent' },
    { path: '/syncComponent', component: syncComponent },
    { path: '/asyncComponent1', component: function () {
      return {
        component: asyncComponent(),
        loading: LoadingComponent
      }
    }}
  ]
});

new Vue({
  el: "#app",
  router: router
});

以上代码模拟了异步加载,但是asyncComponent1并没有显示loading状态。

如果间接在组件中使用loading是可以显示loading状态的。
JS Bin on jsbin.com

var syncComponent = { template: '<div>Sync Component</div>' }

var asyncComponent = function () {
  return new Promise(function (resolve) {
    setTimeout(function() {
      resolve({ template: '<div>Async Component</div>' })
    }, 1000)
  })
}

var LoadingComponent = { template: '<h3>Loading...</h3>' }

var AsyncLoad = function(asyncComponent) {
  return new Promise(function (resolve) {
    resolve({
      name: 'AsyncLoad',
      render: function(h) {
        return h('loading');
      },
      components: {
        loading: function() {
          return {
            component: asyncComponent,
            loading: LoadingComponent
          };
        }
      }
    });
  });
};

var router = new VueRouter({
  routes: [
    { path: '/', redirect: '/syncComponent' },
    { path: '/syncComponent', component: syncComponent },
    { path: '/asyncComponent1', component: function () {
      return AsyncLoad(asyncComponent())
    }}
  ]
});

new Vue({
  el: "#app",
  router: router
});

其中AsyncLoad是一个组件,其中包含了一个异步组件loading,通过loading异步加载实际需要的组件并显示loading动画。

查看Vue Router的代码发现resolveAsyncComponents方法只关注Component的异步加载,没有使用loading属性。而Vue的代码同样有resolveAsyncComponents方法,这个方法既实现了Component的异步加载也实现了loading的显示。

这两天查看文档和代码发现很多设计精巧的代码和技术细节,有可能是我理解的不对或使用方法有误,不过我还是觉得路由的异步加载如果能直接支持loading状态更好,就不用使用beforeEach和afterEach来判断路由状态了,使用更加方便一点。

请大神回答一下是我的路由配置有问题还是Vue Router不支持loading状态,那么官方文档上那句话表达什么意思?


#2

component 接受一个返回值为 Promise 的函数,但你的代码里直接执行这个函数了,相当于把那个 Promise 赋给了 component