1. 程式人生 > >Vue非同步元件處理路由元件載入狀態

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: 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元件內的圖片資源等有可能出現無法載入的問題)