详解基于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 相关文章推荐
javascript instanceof,typeof的区别
Mar 24 Javascript
jQuery的写法不同导致的兼容性问题的解决方法
Jul 29 Javascript
script标签属性type与language使用选择
Dec 02 Javascript
Javascript writable特性介绍
Feb 27 Javascript
JavaScript移除数组内重复元素的方法
Mar 18 Javascript
JS中的THIS和WINDOW.EVENT.SRCELEMENT详解
May 25 Javascript
jQuery实现Tab选项卡切换效果简单演示
Nov 23 Javascript
解决jquery无法找到其他父级子集问题的方法
May 10 Javascript
JS 数字转换为大写金额的简单实例
Aug 04 Javascript
详解Jquery EasyUI tree 的异步加载(遍历指定文件夹,根据文件夹内的文件生成tree)
Feb 11 Javascript
如何选择适合你的JavaScript框架
Nov 20 Javascript
示例vue 的keep-alive缓存功能的实现
Dec 13 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
PHP5.0正式发布 不完全兼容PHP4 新增多项功能
2006/10/09 PHP
推荐个功能齐全的发送PHP邮件类
2007/01/03 PHP
CI框架学习笔记(一) - 环境安装、基本术语和框架流程
2014/10/26 PHP
php实现把url转换迅雷thunder资源下载地址的方法
2014/11/07 PHP
php实现微信支付之退款功能
2018/05/30 PHP
Laravel框架路由管理简单示例
2019/05/07 PHP
php解决约瑟夫环算法实例分析
2019/09/30 PHP
Node.js开发者必须了解的4个JS要点
2016/02/21 Javascript
好好了解一下Cookie(强烈推荐)
2016/06/14 Javascript
使用ionic在首页新闻中应用到的跑马灯效果的实现方法
2017/02/13 Javascript
vue-router单页面路由
2017/06/17 Javascript
微信小程序之选项卡的实现方法
2017/09/29 Javascript
AngularJs分页插件使用详解
2018/06/30 Javascript
vue2.0页面前进刷新回退不刷新的实现方法
2018/07/31 Javascript
vue下history模式刷新后404错误解决方法
2018/08/18 Javascript
记一次webapck4 配置文件无效的解决历程
2018/09/19 Javascript
Angular中使用ng-zorro图标库部分图标不能正常显示问题
2019/04/22 Javascript
150行Node.js实现的dns代理工具
2019/08/02 Javascript
深入webpack打包原理及loader和plugin的实现
2020/05/06 Javascript
解决vue单页面应用打包后相对路径、绝对路径相关问题
2020/08/14 Javascript
JS数组索引检测中的数据类型问题详解
2021/01/11 Javascript
[04:44]显微镜下的DOTA2第二期——你所没有注意到的细节
2014/06/20 DOTA
利用Python2下载单张图片与爬取网页图片实例代码
2017/12/25 Python
python从ftp获取文件并下载到本地
2020/12/05 Python
Html5 实现微信分享及自定义内容的流程
2019/08/20 HTML / CSS
ProBikeKit澳大利亚:自行车套件,跑步和铁人三项装备
2016/11/30 全球购物
酒店服务实习自我鉴定
2013/09/22 职场文书
专业幼师实习生自我鉴定范文
2013/12/08 职场文书
消防安全责任书
2014/04/14 职场文书
承诺书模板
2014/08/30 职场文书
2014大四本科生自我鉴定总结
2014/10/04 职场文书
大学生自荐信怎么写
2015/03/26 职场文书
2015年双拥工作总结
2015/04/08 职场文书
《山中访友》教学反思
2016/02/24 职场文书
情况说明书格式及范文
2019/06/24 职场文书
漫改真人电影「萌系男友是燃燃的橘色」公开先导视觉图
2022/03/21 日漫