在大型单页面应用中,处于对性能的考虑和首屏加载速度的要求,咱们通常都会使用webpack的代码分割和vue-router的路由懒加载功能将咱们的代码分红一个个模块,而且只在须要的时候才从服务器加载一个模块。html
可是这种解决方案也有其问题,当网络环境较差时,咱们去首次访问某个路由模块,因为加载该模块的资源须要必定的时间,那么该段时间内,咱们的应用就会处于无响应的状态,用户体验极差。vue
这种状况,咱们一方面能够缩小路由模块代码的体积,静态资源使用cdn存储等方式缩短加载时间,另外一方面则能够路由组件上使用异步组件,显示loading和error等状态,使用户可以获得清晰明了的操做反馈。
Vue官方文档-动态组件&异步组件webpack
/**
* 处理路由页面切换时,异步组件加载过渡的处理函数
* @param {Object} AsyncView 须要加载的组件,如 import('@/components/home/Home.vue')
* @return {Object} 返回一个promise对象
*/
function lazyLoadView (AsyncView) {
const AsyncHandler = () => ({
// 须要加载的组件 (应该是一个 `Promise` 对象)
component: AsyncView,
// 异步组件加载时使用的组件
loading: require('@/components/public/RouteLoading.vue').default,
// 加载失败时使用的组件
error: require('@/components/public/RouteError.vue').default,
// 展现加载时组件的延时时间。默认值是 200 (毫秒)
delay: 200,
// 若是提供了超时时间且组件加载也超时了,
// 则使用加载失败时使用的组件。默认值是:`Infinity`
timeout: 10000
});
return Promise.resolve({
functional: true,
render (h, { data, children }) {
return h(AsyncHandler, data, children);
}
});
}
复制代码
const helloWorld = () => lazyLoadView(import('@/components/helloWorld'))
复制代码
routes: [
{
path: '/helloWorld',
name: 'helloWorld',
component: helloWorld
}
]
复制代码
至此,改造已经完成,当你首次加载某一个组件的资源时(能够将网速调为 slow 3g,效果更明显),就会显示你在loading组件的内容,而当超出超时时间仍未加载完成该组件时,那么将显示error组件的内容(建议error组件尽可能简单,由于当处于低速网络或者断网状况下时,error组件内的图片资源等有可能出现没法加载的问题)git
在使用本文的配置对路由引入方式进行重构后,会出现路由钩子没法使用的问题,这个问题也是刚刚发现,在查阅资料后发现,vue-router目前对于这种使用方法是不支持的...
官方解释为:github
> WARNING: Components loaded with this strategy will **not** have access to
in-component guards, such as `beforeRouteEnter`, `beforeRouteUpdate`, and
`beforeRouteLeave`. If you need to use these, you must either use route-level
guards instead or lazy-load the component directly, without handling loading
state.
复制代码
连接:github.com/vuejs/vue-r…web