思索-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 ...
随机推荐
- java基础(七)--基本类型转换
一.转换规则 1.类型转换的原则是: 小容量可以自动转成大容量,大容量转成小容量,需要强制转换,有些类型之前不能转换 判断以下语句是否符合要求 2.默认的识别数字 整数默认->int 浮点数默认 ...
- Redis 和 memcache 简单比较
1.Redis不仅仅支持简单的key-value类型的数据,同时还提供list.set.zset.hash等数据结构的存储. 2.Redis支持master-slave(主--从)模式应用. 3.Re ...
- 你一个 F12 能秒我?
参考文章 思路决定成败:F12给了我黑色的眼睛我却用它来挖洞 前言 了解大佬的思路才知道自己现在学的到底有多浅. 还没有到点,我就已经进入状态了,生而为人,我很抱歉. F12 的骚操作 Element ...
- 十进制转换为其他进制(不使用format)
base = [str(x) for x in range(10)] + [chr(x) for x in range(ord('A'), ord('A') + 6)] # ['0', '1', '2 ...
- Python file() 函数
描述 file() 函数用于创建一个 file 对象,它有一个别名叫 open(),更形象一些,它们是内置函数.参数是以字符串的形式传递的.每组词 www.cgewang.com 更多文件操作可参考: ...
- AJAX 是什么?
AJAX 简介 AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术. AJAX 是什么? AJAX = Asynchronous JavaScript and XML. AJAX ...
- Python os.lstat() 方法
概述 os.lstat() 方法用于类似 stat() 返回文件的信息,但是没有符号链接.在某些平台上,这是fstat的别名,例如 Windows.高佣联盟 www.cgewang.com 语法 ls ...
- PHP localeconv() 函数
实例 查找美国本地的数字格式化信息: <?php setlocale(LC_ALL,"US"); $locale_info = localeconv(); print_r($ ...
- luogu P5289 [十二省联考2019]皮配 背包
LINK:皮配 我承认是一道很难的题目. 不过对于这道题 部分分的提示显得尤为重要. 首先是 40分的暴力dp 很容易想 但是不容易写. 从40分可以发现我们只需要把蓝阵营和鸭派系的人数给存在起来就行 ...
- luogu P4008 [NOI2003]文本编辑器 splay 块状链表
LINK:文本编辑器 这个东西感觉块状链表写细节挺多 (块状链表本来就难写 解释一下块状链表的做法:其实是一个个数组块 然后利用链表给链接起来 每个块的大小为sqrt(n). 这样插入删除的时候直接暴 ...