思索-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 ...
随机推荐
- 大家是怎么做APP接口的版本控制的?欢迎进来看看我的方案。升级版的Versioning
背景 APP不同于网站,网站程序一发版,所有用户看到的都是最新的页面.调用最新的接口,没有新老版本一说.APP一旦下载到用户手机上,用户不更新你拿他一点办法都没有,但是随着业务的调整,同一个接口的请求 ...
- vector 赋初始值的问题
这个,输出为1 这个,啥都输不出来. 据说是因为没有初始化. 其实我搜了一下 vector<vector<int> > A;//正确的定义方式 vector<vector ...
- 预定义的 $_POST 变量用于收集来自 method="post" 的表单中的值
PHP $_POST 变量 在 PHP 中,预定义的 $_POST 变量用于收集来自 method="post" 的表单中的值. $_POST 变量 预定义的 $_POST 变量用 ...
- PHP rsort() 函数
实例 对数组 $cars 中的元素按字母进行降序排序: <?php$cars=array("Volvo","BMW","Toyota" ...
- PHP dechex() 函数
实例 把十进制转换为十六进制: <?phpecho dechex("30") . "<br>";echo dechex("10&qu ...
- 5.21 省选模拟赛 luogu P4297 [NOI2006]网络收费 树形dp
LINK:网络收费 还是自己没脑子. 早上思考的时候 发现树形dp不可做 然后放弃治疗了. 没有合理的转换问题的模型是我整个人最大的败笔. 暴力也值得一提 爆搜之后可以写成FFT的形式的计算贡献的方法 ...
- linux之DHCP服务端搭建 ( ip分配 四个阶段原理)
DHCP服务 ip分配 四个阶段原理 1.DHCP服务目的 协议 作用 租约 原理四个阶段 动态主机配置协议(Dynamic Host Configuration Protocol,动态主机配置协议) ...
- 记不住git命令?试试这个命令浏览网站
Find the right git commands without digging through the web. 找 git 命令,无需谷歌百度,无需 git -help,这个网站以图形界面的 ...
- 学会这些Python美图技巧,就等着女朋友夸你吧
一.前言 Python中有许多用于图像处理的库,像是Pillow,或者是OpenCV.而很多时候感觉学完了这些图像处理模块没有什么用,其实只是你不知道怎么用罢了.今天就给大家带了一些美图技巧,让你的图 ...
- 【Spring注解驱动开发】使用@PropertySource加载配置文件,我只看这一篇!!
写在前面 很多小伙伴都在问:冰河,你的Spring专题更新完了吗?怎么感觉像是写了一半啊?我:没有更新完呀,整个专题预计会有70多篇.那怎么更新了一半就去写别的了呢?那是因为有很多其他的小伙伴在后台留 ...