Vue異步組件處理路由組件加載狀態

問題場景

在大型單頁面應用中,處於對性能的考慮和首屏加載速度的要求,咱們通常都會使用webpack的代碼分割和vue-router的路由懶加載功能將咱們的代碼分紅一個個模塊,而且只在須要的時候才從服務器加載一個模塊。html

可是這種解決方案也有其問題,當網絡環境較差時,咱們去首次訪問某個路由模塊,因爲加載該模塊的資源須要必定的時間,那麼該段時間內,咱們的應用就會處於無響應的狀態,用戶體驗極差。vue

解決方案

這種狀況,咱們一方面能夠縮小路由模塊代碼的體積,靜態資源使用cdn存儲等方式縮短加載時間,另外一方面則能夠路由組件上使用異步組件,顯示loading和error等狀態,使用戶可以獲得清晰明瞭的操做反饋。
Vue官方文檔-動態組件&異步組件webpack

具體實現

  1. 聲明方法,基於Vue動態組件工廠函數來返回一個Promise對象
/**
 * 處理路由頁面切換時,異步組件加載過渡的處理函數
 * @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);
    }
  });
}
複製代碼
  1. 引入路由
const helloWorld = () => lazyLoadView(import('@/components/helloWorld'))
複製代碼
  1. vue-router中使用
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

關於使用異步組件後路由鉤子失效的解決方法

  1. 須要使用路由鉤子的頁面放棄異步加載,使用普通的懶加載
  2. 使用created, mounted等鉤子替代路由鉤子 其餘辦法進一步查找中,歡迎各位在評論中提出問題和解決方案。
相關文章
相關標籤/搜索