天天看點

Vue異步元件處理路由元件加載狀态

問題場景

在大型單頁面應用中,處于對性能的考慮和首屏加載速度的要求,我們一般都會使用webpack的代碼分割和vue-router的路由懶加載功能将我們的代碼分成一個個子產品,并且隻在需要的時候才從伺服器加載一個子產品。

但是這種解決方案也有其問題,當網絡環境較差時,我們去首次通路某個路由子產品,由于加載該子產品的資源需要一定的時間,那麼該段時間内,我們的應用就會處于無響應的狀态,使用者體驗極差。

解決方案

這種情況,我們一方面可以縮小路由子產品代碼的體積,靜态資源使用cdn存儲等方式縮短加載時間,另一方面則可以路由元件上使用異步元件,顯示loading和error等狀态,使使用者能夠得到清晰明了的操作回報。

Vue官方文檔-動态元件&異步元件

具體實作

  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: ,
    // 如果提供了逾時時間且元件加載也逾時了,
    // 則使用加載失敗時使用的元件。預設值是:`Infinity`
    timeout: 
  });
  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元件内的圖檔資源等有可能出現無法加載的問題)

繼續閱讀