如今移动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>
最后欢迎你们讨论或提供更好的解决方案。