如今移動web app愈來愈熱門了,許多公司開始嘗試使用angular、react、vue等MVVM框架來開發單頁架構的web app。但在開發web app時,若是但願頁面的導航體驗也接近原生應用,那通常都會遇到這兩個問題:javascript
筆者開發了一個基於vue與vue-router的導航庫vue-navigation,來幫助開發者來解決這些問題,下面是問題的解決思路。html
先說第一個問題。和原生app不同,瀏覽器中主要有這幾個限制:vue
解決方案是本身維護一份瀏覽記錄,每次url改變時,經過與記錄的瀏覽記錄做對比,從而判斷出前進後退行爲:java
另外,應用的路由路徑中可能容許相同的路由出現屢次(例如A->B->A),因此給每一個路由添加一個key值來區分相同路由的不一樣實例。node
這個瀏覽記錄須要存儲在sessionStorage
中,這樣用戶刷新後瀏覽記錄也能夠恢復。react
識別出後退行爲後,下一步就是像原生同樣恢復以前的頁面了。git
一種方案是頁面繼續存儲在DOM中,添加樣式display: none
來告訴瀏覽器不渲染該元素,可是緩存的頁面多了DOM就會變得很大,會影響頁面的性能,本文不討論這個方案。github
另外一種方案是將數據緩存到內存中,開發者須要將頁面的數據存儲起來,當返回到該頁面時,再根據數據將頁面恢復。可是這樣每一個頁面存儲的數據不通,通常須要進行額外的編碼,若是有一種更底層的方案能解決這個問題,而且對開發者是透明的,就最好了,因此嘗試並開發了vue-navigation。web
在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來開發的,可是思路是不變的,使用其餘框架也能夠作到一樣的事情。
仍是安利一下vue和vue-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>
最後歡迎你們討論或提供更好的解決方案。