思索-js 页面ID识别及数据缓存
思索-页面ID识别及数据缓存
页面 ID 识别的思路
多页应用在移动端是较为常见的一种架构,它可以和APP 内的 webview 配合,达到类似原生的体验,这一点是单页应用无法做到的(比如手势滑动等,会直接关闭 webview)。
多页应用中,使用location 进行跳转时页面会被销毁,页面后退或刷新时,页面就会是一个全新的加载,在一些需要页面级的缓存数据时,没办法通过简单的 sessionStorage 进行缓存,主要是因为 sessionStorage 生命周期存在一个上下文,与本页面关联,或者重新进入本页面的时候都会一直存在。而我们要做到的效果是:刷新/后退时页面数据缓存,重新进入页面不缓存。
为什么我们难以实现页面 ID 的识别?因为页面本身是无状态的,如果 URL 唯一,那么可以把 URL 当作是页面的 ID,如果页面入口不是自己控制,那我们没办法保证 URL 会是唯一的。想要给页面加个 ID,最先想到的是自己维护一套 history,每次生成时候保存页面 ID,根据前进或者是后退来识别当前页面位于哪个位置。
判断页面的前进后退,我们可以用浏览器提供的接口:performance.navigation.type 来判断(参见:https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming,
function getNaviagteType () {
const { performance } = window
// performance navigation 兼容 ios9+, Android 全部, 低于该版本默认全部是新打开
if (performance) {
// 新的 performance 接口
if (typeof performance.getEntriesByType === 'function') {
const perfEntries = performance.getEntriesByType('navigation') || []
const [timing] = perfEntries
if (timing && timing.type) {
return timing.type
}
}
const typeMap = ['navigate', 'reload', 'back_forward']
// 旧的 performance 接口
if (performance.navigation && performance.navigation.type != null) {
return typeMap[performance.navigation.type] || 'reserved'
}
}
return 'not_support'
}
根据这个来判断,我们就可以拿到需要的导航类型。这样和 sessionStorage 配合,就可以维护一套可用的历史记录版本了。但是如果我们只是要页面ID 级别的缓存呢?
页面级别数据缓存
如果只需要数据缓存,我们就不需要考虑维护 ID 了。因为正常情况下我们的历史记录里面不会出现两次一样的 URL,或者是出现也不影响我们的页面表现。具体代码如下:
const SESSION_KEY = 'page-cache'
const { sessionStorage } = window
function safeJsonParse(str, defaultValue) {
if (!str) {
return defaultValue;
}
let res
try {
res = JSON.parse(str)
} catch (err) {
// eslint-disable-next-line no-console
console.error(err)
res = defaultValue
}
return res || defaultValue
}
/**
* 初始化页面数据
* @param {*} cacheData 数据对象
* @param {*} pageId 页面ID
* @param {*} usePreData 是否使用上次缓存的值
*/
function initPageData (cacheData, pageId, usePreData) {
const initData = cacheData
initData.pageId = pageId
initData.data = initData.data || {}
initData.data[pageId] = (usePreData ? initData.data[pageId] : null) || {}
sessionStorage.setItem(SESSION_KEY, JSON.stringify(initData))
}
/**
* 初始化页面数据
*/
function init (pageId = window.location.pathname) {
const cacheData = safeJsonParse(sessionStorage.getItem(SESSION_KEY), {})
const navType = getNaviagteType()
// 这几种情况下不清除数据,直接沿用上一次数据
if (cacheData.pageId && ['back_forward', 'reload', 'not_support'].indexOf(navType) > -1) {
initPageData(cacheData, pageId, true)
return cacheData
}
initPageData(cacheData, pageId, false)
return cacheData
}
init()
/**
* 获取全量的 cache 数据
*/
function getFullCacheData () {
const cacheData = safeJsonParse(sessionStorage.getItem(SESSION_KEY), null)
return cacheData || init()
}
/**
* 获取缓存中的数据
*/
function getPageCache (cacheData = getFullCacheData()) {
return cacheData.data[cacheData.pageId] || {}
}
/**
* 获取缓存中指定 key 的数据
* @param {*} key key 值
*/
function getPageCacheItem (key) {
const cacheData = getPageCache()
return cacheData[key]
}
/**
* 设置缓存内容
* @param {*} key key
* @param {*} value 对应的数据
*/
function setPageCacheItem (key, value) {
const fullData = getFullCacheData()
const cacheData = getPageCache(fullData)
cacheData[key] = value
sessionStorage.setItem(SESSION_KEY, JSON.stringify(fullData))
}
/**
* 移除缓存中页面的某个数据
* @param {*} key 条目名称
*/
function removePageCacheItem (key) {
const fullData = getFullCacheData()
const cacheData = getPageCache(fullData)
delete cacheData[key]
sessionStorage.setItem(SESSION_KEY, JSON.stringify(fullData))
}
/**
* 移除缓存
*/
function clearPageCache () {
const fullData = getFullCacheData()
fullData.data[fullData.pageId] = {}
sessionStorage.setItem(SESSION_KEY, JSON.stringify(fullData))
}
const cache = {
init,
getAll: getPageCache,
getItem: getPageCacheItem,
setItem: setPageCacheItem,
removeItem: removePageCacheItem,
clear: clearPageCache
}
该方案的主要缺陷是:
- 不兼容 IOS9,所以需要考虑到失效情况下你的业务是什么表现
- 历史记录里面存在相同的url,那缓存数据会产生污染
如果你有兴趣的话,可以实现一个页面 ID 的功能,在初始化的时候设置 pageId 的值就可以了。
思索-js 页面ID识别及数据缓存的更多相关文章
- 从微信小程序到鸿蒙js开发【12】——storage缓存&自动登录
鸿蒙入门指南,小白速来!从萌新到高手,怎样快速掌握鸿蒙开发?[课程入口] 正文: 在应用开发时,我们常需要将一些数据缓存到本地,以提升用户体验.比如在一个电商的app中,如果希望用户登录成功后,下次打 ...
- Servlet数据缓存
缓存是提高数据访问能力,降低服务器压力的一种必要的方式,今天我要说的数据缓存方式有两种,1-->session对单个数据访问接口页面的数据进行缓存,2-->单例模式对整个servlet页面 ...
- 利用js对象将iframe数据缓存, 实现子页面跳转后, 返回时不丢失之前填写的数据
利用js对象将iframe数据缓存, 实现子页面跳转后, 返回时不丢失之前填写的数据 实现描述:将数据存放在js对象中, 然后放在父页面的document对象中, 在页面刷新的时候将父页面的值取出来, ...
- 第十七课:js数据缓存系统的原理
这一章主要讲的是jQuery的缓存系统的历史发展,以及他自己的框架的缓存系统的实现.都是源码解析. 我就挑几个重点讲下: (1)jQuery的缓存机制的原理 jQuery的缓存机制实现的原理是在元素中 ...
- 腾讯面试题,js处理1千万条数据排序并且页面不卡顿
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- js/jquery控制页面动态加载数据 滑动滚动条自动加载事件--转他人的
js/jquery控制页面动态加载数据 滑动滚动条自动加载事件--转他人的 相信很多人都见过瀑布流图片布局,那些图片是动态加载出来的,效果很好,对服务器的压力相对来说也小了很多 有手机的相信都见过这样 ...
- JS页面刷新保持数据不丢失
转自:https://blog.csdn.net/qq_32439101/article/details/78134877 下面是 DOM Storage 的接口定义: interface Stora ...
- angular js 页面修改数据存入数据库
一.编写service,修改数据要根据ID回显数据 //根据ID查询 public Brand findById(Long id); //修改 public int update(Brand bran ...
- jQuery数据缓存方案详解:$.data()的使用
我们经常使用隐藏控件或者是js全局变量来临时存储数据,全局变量容易导致命名污染,隐藏控件导致经常读写dom浪费性能.jQuery提供了自己的数据缓存方案,能够达到和隐藏控件.全局变量相同的效果,但是j ...
随机推荐
- 浅谈Redis未授权访问漏洞
Redis未授权访问漏洞 Redis是一种key-value键值对的非关系型数据库 默认情况下绑定在127.0.0.1:6379,在没有进行采用相关的策略,如添加防火墙规则避免其他非信任来源ip访问等 ...
- org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/book]] Tomcat ServletXml 异常
此异常是因为xml配置serlvet-url-pattern缺少’/’ 应该改为 /regist 背景: 写了base标签 form表单的action属性的值 个人分析: ️表单提交时 ...
- luogu P2607 [ZJOI2008]骑士 tarjan dp
LINK:骑士 本来是不打算写的 发现这道题在tarjan的时候有一个坑点 所以写出来记录一下. 可以发现图可能是不连通的 且一个连通块中是一个奇环树. 做法:类似tarjan找割点 然后把环给拉出来 ...
- CF R639 div 2 E Quantifier Question 数学 dfs 图论
LINK:Quantifier Question 题面过长 引起不适 读题花了好长时间 对于 和 存在符合不是很熟练 导致很懵逼的做完了. 好在还算很好想.不过wa到了一个坑点上面 自闭一大晌 还以为 ...
- 牛客练习赛60 D 斩杀线计算大师
LINK:斩杀线计算大师 给出a,b,c三个值 求出 ax+by+cz=k的x,y,z的正整数解 保证一定有解. 考虑两个数的时候 ax+by=k 扩展欧几里得可以解决. 三个数的时候 一个暴力的想法 ...
- canvas小画板--(1)平滑曲线
功能需求 项目需求:需要实现一个可以自由书写的小画板 简单实现 对于熟悉canvas的同学来说,这个需求很简单,短短几十行代码就能实现: <!doctype html> <html& ...
- Android Studio--APK打包
首先在app的build.gradle里面加一下代码 lintOptions { checkReleaseBuilds false abortOnError false } 在上方Build里面找到G ...
- python实现单张图像拼接与批量图片拼接
本文实例为大家分享了python实现图像拼接的具体代码,供大家参考,具体内容如下 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经 ...
- 几行python代码实现钉钉自动打卡,网友:终于告别缺勤了
前言 众所周知因为疫情的原因大家都没有办法上学和上班,“钉钉”这个app起到了重大的作用.学校为了学生成绩开启“钉钉”之路.老师也成一个“合格”的主播,感谢XXX童鞋的礼物.666扣起来 老师为了营造 ...
- JS笔记 数据类型分类以及转换
数据类型分类 原始类型(基本类型.值类型) 1.number 类型 数字类型,表示32(4字节)的整数以及64位(8字节)的浮点数 整数 bit:位 8bit=1byte 1024byte=1kb千字 ...