详解基于vue的移动web app页面缓存解决方案


Posted in Javascript onAugust 03, 2017

现在移动web app越来越热门了,许多公司开始尝试使用angular、react、vue等MVVM框架来开发单页架构的web app。但在开发web app时,如果希望页面的导航体验也接近原生应用,那一般都会遇到这两个问题:

  • 识别前进后退行为
  • 后退时恢复之前的页面

笔者开发了一个基于vue与vue-router的导航库vue-navigation,来帮助开发者来解决这些问题,下面是问题的解决思路。

识别前进后退

先说第一个问题。和原生app不一样,浏览器中主要有这几个限制:

  • 没有提供前进后退的事件
  • 不允许开发者读取浏览记录
  • 用户可以手动输入地址,或使用浏览器提供的前进后退来改变url

解决方案是自己维护一份浏览记录,每次url改变时,通过与记录的浏览记录作对比,从而判断出前进后退行为:

  • url存在于浏览记录中即为后退
  • url不存在于浏览记录中即为前进
  • url在浏览记录的末端即为刷新

另外,应用的路由路径中可能允许相同的路由出现多次(例如A->B->A),所以给每个路由添加一个key值来区分相同路由的不同实例。

这个浏览记录需要存储在sessionStorage中,这样用户刷新后浏览记录也可以恢复。

后退时恢复之前的页面

识别出后退行为后,下一步就是像原生一样恢复之前的页面了。

一种方案是页面继续存储在DOM中,添加样式display: none来告诉浏览器不渲染该元素,但是缓存的页面多了DOM就会变得很大,会影响页面的性能,本文不讨论这个方案。

另一种方案是将数据缓存到内存中,开发者需要将页面的数据存储起来,当返回到该页面时,再根据数据将页面恢复。但是这样每个页面存储的数据不通,一般需要进行额外的编码,如果有一种更底层的方案能解决这个问题,并且对开发者是透明的,就最好了,所以尝试并开发了vue-navigation。

在vue-navigation 0.x版本的时候,借助了vue的keep-alive来缓存页面,但是keep-alive是根据组件的name或tag来决定缓存的,所以带来了很多限制。

通过拜读keep-alive的源码,了解到它的缓存机制后,就自己实现了一个管理缓存的组件,来灵活地缓存子组件,实现思路如下:

  1. 每次render时,先取到子组件的vnode(vue的虚拟dom)
  2. 计算出vnode的key,把key值赋给vnode避免vue-router复用组件实例
  3. 根据key值判断该节点是否已缓存
    1. 已缓存:将缓存的实例赋给componentInstance,这样vue就会根据这个实例来恢复组件
    2. 未缓存:将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>

最后欢迎大家讨论或提供更好的解决方案。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
原生js实现的贪吃蛇网页版游戏完整实例
May 18 Javascript
jquery实现简单的二级导航下拉菜单效果
Sep 07 Javascript
详解JavaScript中的Unescape()和String() 函数
Nov 09 Javascript
js实现无缝循环滚动
Jun 23 Javascript
javascript中的面向对象
Mar 30 Javascript
js 显示日期时间的实例(时间过一秒加1)
Oct 25 Javascript
基于vue中解决v-for使用报红并出现警告的问题
Mar 03 Javascript
Angular动态绑定样式及改变UI框架样式的方法小结
Sep 03 Javascript
Vue唯一可以更改vuex实例中state数据状态的属性对象Mutation的讲解
Jan 18 Javascript
vue实现随机验证码功能的实例代码
Apr 30 Javascript
jQuery实现图片下载代码
Jul 18 jQuery
vue-loader中引入模板预处理器的实现
Sep 04 Javascript
Bootstrap与Angularjs的模态框实例代码
Aug 03 #Javascript
基于 Bootstrap Datetimepicker 联动
Aug 03 #Javascript
详解react-webpack2-热模块替换[HMR]
Aug 03 #Javascript
webpack开发跨域问题解决办法
Aug 03 #Javascript
详解Vuejs2.0 如何利用proxyTable实现跨域请求
Aug 03 #Javascript
react-native ListView下拉刷新上拉加载实现代码
Aug 03 #Javascript
解决ionic和angular上拉加载的问题
Aug 03 #Javascript
You might like
跟我学小偷程序之成功偷取首页(第三天)
2006/10/09 PHP
十天学会php之第一天
2006/10/09 PHP
如何从一个php文件向另一个地址post数据,不用表单和隐藏的变量的
2007/03/06 PHP
php单例模式实现(对象只被创建一次)
2012/12/05 PHP
Django 中 cookie的使用
2017/08/17 PHP
javascript 鼠标拖动图标技术
2010/02/07 Javascript
JS实现QQ图片一闪一闪的效果小例子
2013/07/31 Javascript
js open() 与showModalDialog()方法使用介绍
2013/09/10 Javascript
jQuery实现首页顶部可伸缩广告特效代码
2015/04/15 Javascript
JavaScript入门系列之知识点总结
2016/03/24 Javascript
详谈JavaScript的闭包及应用
2017/01/17 Javascript
使用JavaScript判断用户输入的是否为正整数(两种方法)
2017/02/05 Javascript
vue 怎么创建组件及组件使用方法
2017/07/27 Javascript
Vue 组件间的样式冲突污染
2017/08/31 Javascript
ng-alain表单使用方式详解
2018/07/10 Javascript
搭建vue开发环境
2018/07/19 Javascript
玩转Koa之核心原理分析
2018/12/29 Javascript
nodejs中request库使用HTTPS代理的方法
2019/04/30 NodeJs
Vue中qs插件的使用详解
2020/02/07 Javascript
Python函数嵌套实例
2014/09/23 Python
常见python正则用法的简单实例
2016/06/21 Python
Python文件操作,open读写文件,追加文本内容实例
2016/12/14 Python
Python可变参数用法实例分析
2017/04/02 Python
Python实现将MySQL数据库表中的数据导出生成csv格式文件的方法
2018/01/11 Python
django解决跨域请求的问题
2018/11/11 Python
python中import与from方法总结(推荐)
2019/03/21 Python
详解Python:面向对象编程
2019/04/10 Python
html5小技巧之通过document.head获取head元素
2014/06/04 HTML / CSS
家得宝墨西哥官网:The Home Depot墨西哥
2019/11/18 全球购物
C# .NET面试题
2015/11/28 面试题
Servlet如何得到客户端机器的信息
2014/10/17 面试题
检讨书1000字
2014/10/11 职场文书
老人再婚离婚协议书范本
2014/10/27 职场文书
沈阳故宫导游词
2015/01/31 职场文书
领导干部学习十八届五中全会精神心得体会
2016/01/05 职场文书
党员反邪教心得体会
2016/01/15 职场文书