基於vue的移動web app頁面緩存解決方案

如今移動web app愈來愈熱門了,許多公司開始嘗試使用angular、react、vue等MVVM框架來開發單頁架構的web app。但在開發web app時,若是但願頁面的導航體驗也接近原生應用,那通常都會遇到這兩個問題:javascript

  • 識別前進後退行爲
  • 後退時恢復以前的頁面

筆者開發了一個基於vue與vue-router的導航庫vue-navigation,來幫助開發者來解決這些問題,下面是問題的解決思路。html

識別前進後退

先說第一個問題。和原生app不同,瀏覽器中主要有這幾個限制:vue

  • 沒有提供前進後退的事件
  • 不容許開發者讀取瀏覽記錄
  • 用戶能夠手動輸入地址,或使用瀏覽器提供的前進後退來改變url

解決方案是本身維護一份瀏覽記錄,每次url改變時,經過與記錄的瀏覽記錄做對比,從而判斷出前進後退行爲:java

  • url存在於瀏覽記錄中即爲後退
  • url不存在於瀏覽記錄中即爲前進
  • url在瀏覽記錄的末端即爲刷新

另外,應用的路由路徑中可能容許相同的路由出現屢次(例如A->B->A),因此給每一個路由添加一個key值來區分相同路由的不一樣實例。node

這個瀏覽記錄須要存儲在sessionStorage中,這樣用戶刷新後瀏覽記錄也能夠恢復。react

後退時恢復以前的頁面

識別出後退行爲後,下一步就是像原生同樣恢復以前的頁面了。git

一種方案是頁面繼續存儲在DOM中,添加樣式display: none來告訴瀏覽器不渲染該元素,可是緩存的頁面多了DOM就會變得很大,會影響頁面的性能,本文不討論這個方案。github

另外一種方案是將數據緩存到內存中,開發者須要將頁面的數據存儲起來,當返回到該頁面時,再根據數據將頁面恢復。可是這樣每一個頁面存儲的數據不通,通常須要進行額外的編碼,若是有一種更底層的方案能解決這個問題,而且對開發者是透明的,就最好了,因此嘗試並開發了vue-navigationweb

vue-navigation 0.x版本的時候,藉助了vue的keep-alive來緩存頁面,可是keep-alive是根據組件的name或tag來決定緩存的,因此帶來了不少限制。vue-router

經過拜讀keep-alive的源碼,瞭解到它的緩存機制後,就本身實現了一個管理緩存的組件,來靈活地緩存子組件,實現思路以下:

  • 每次render時,先取到子組件的vnode(vue的虛擬dom)
  • 計算出vnode的key,把key值賦給vnode避免vue-router複用組件實例
  • 根據key值判斷該節點是否已緩存

    • 已緩存:將緩存的實例賦給componentInstance,這樣vue就會根據這個實例來恢復組件
    • 未緩存:將vnode存儲到內存中,下次返回到該頁面時能夠從內存中恢復

另外還須要添加一個清除緩存的邏輯,當本身維護的瀏覽記錄變化時,根據瀏覽記錄清除不須要的緩存(例如當前的路由是:A->B->C,用戶從C直接返回到了A,那麼B和C都須要從緩存中刪除)。

最後

雖然是基於vue來開發的,可是思路是不變的,使用其餘框架也能夠作到一樣的事情。

仍是安利一下vuevue-navigation。使用插件後,再將router-view放在navigation下就有緩存功能了。

main.js

import Vue from 'vue'
import router from './router' // vue-router 實例
import Navigation from 'vue-navigation'
Vue.use(Navigation, {router})
// 啓動你的應用...

App.vue

<template>
  <navigation>
    <router-view></router-view>
  </navigation>
</template>

最後歡迎你們討論或提供更好的解決方案。

相關文章
相關標籤/搜索