概述
关于 H5 项目中本地储存机制的思考
分类
目前在浏览器存储数据主要有三种方式:
本地储存
-
cookie
在 h5 之前,存储主要用的是 cookie。cookie 会随着每次 http 请求头信息一起发送,常用作用户登录信息,埋点回传等操作 -
localStorage
localStorage(本地存储),可以长期存储数据,没有时间限制,一天,一年,两年甚至更长 -
sessionStorage
sessionStorage(会话存储),只有在浏览器被关闭之前使用,创建另一个页面时也可使用,关闭浏览器之后数据就会消失
注意
通过点击链接打开的新标签页之间是属于同一个 session ,但新开标签页是会初始化一个新 session,即使浏览器不动 + 网站一样,它们也不属于同一个 sessionwebStorage 和 cookie 不是完全相同的概念:Cookie 是不可或缺的,他的作用是与服务器进行交互,作为 HTTP 规范的一部分而存在 ,而 Web Storage 仅仅是为了在本地“存储”数据而生。
网络缓存
- Service Worker
运行在浏览器背后的独立线程,Service Worker 的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的
- Memory Cache
内存缓存,主要包含的是当前中页面中已经抓取到的资源,例如页面上已经下载的样式、脚本、图片等
- Disk Cache
硬盘缓存,比之 Memory Cache 胜在容量和存储时效性上
- Push Cache
Push Cache(推送缓存)是 HTTP/2 中的内容,当以上三种缓存都没有命中时,它才会被使用。它只在会话(Session)中存在,一旦会话结束就被释放,并且缓存时间也很短暂
离线缓存
html标签中添加manifest属性
-
离线缓存是针对整个应用,浏览器缓存是单个文件
-
离线缓存断网了还是可以打开页面,浏览器缓存不行
-
离线缓存可以主动通知浏览器更新资源
数据存储的用处
减少请求频率,减轻服务器压力
减少加载时间,提升用户体验
实现跨页面通信
在 C 端的项目中由于页面大小有限,相比于 B 端为了实现更多的功能,只能增加页面的层级关系和互相跳转。以 H5 为例,用户在外卖选择自己地址=》点单=》下单=》支付=》详情,这些都是彼此独立的页面,如果中间涉及到用户的返回,刷新或再次进入的话,都会存在数据不同步和错误的风险。
为了解决这种风险,在 H5 项目中最常用的方式是采用路由进行参数的传递,再在页面加载时向服务器获取最新数据,这样的方式好处是能够保证数据的实时性,也防止了本地储存或缓存可能导致的数据错乱,但在有些场景就会很影响用户的体验感,更严重的是可能会让请求互相干扰,阻塞页面的加载
例如定位操作,在进入门店点单时头部的门店信息部分和切换门店都是各自独立的 widget,再被引入点单页,这两个组件都会包含微信定位
如图所示,由于门店列表模块和门店点单属于同一个页面,点击切换门店就会展示门店列表。
现在假设这么一种操作:
用户在首次进入门店点单页面的时候,页面内的两个组件在加载时就开始同时走微信定位的接口,这看起来没什么关系,在安卓手机上也的确如此,但如果在苹果手机上就会发生一直加载的情况。
即使是对微信定位用 try-catch 包裹,依旧捕获不到任何异常,经过调试发现,是两个定位产生了互相干扰,导致一直在定位没有结果,基于安卓特殊的处理机制,有效的避开了这种干扰,而 ios 并没有针对这情况进行处理,于是 ios 就会表现为页面一直在刷新。
但问题是,真正定位的过程是封装在微信内部的,页面中不能对这种问题作出拦截处理,于是乎一种有效的处理方式,就是给首页的门店信息定位过程结束后加入一个标识符,当知道门店信息模块的定位结束后,再去触发门店列表的定位过程,这样就有效的将两个定位过程隔离开来,解决了缺陷。
或许你会说何必这么麻烦?通过状态管理,只定位一次就行了呗,但前面说过这是两个独立的 widget,如果想用状态管理解决通信问题,就得将口子开大,这也是框架编写者所不希望看到的增加了耦合度的情况,再者万一用户刷新呢,不还是得再来一遍?
所以除了状态判断,其实本地储存就似乎成了最佳的解决方案。不过即使是使用本地储存,sessionStorage 还是 localStorage 也是需要注意的点,针对定位这种大概率会随着页面开启关闭而变化的数据,自然是 sessionStorage 更有价值。
同时对于一些不是那么核心的功能,属于非重要的展示数据,例如搜索框的历史搜索记录。
这种更多地只是为用户提供一个快速回溯历史记录的输入操作,对于这种本身就是锦上添花的功能,还去向服务器请求未免有些多余了,再者如果将这些数据写进地址栏,未免过于臃肿。这些数据即使发生了问题,用户重搜一下就行了,也不会影响主流程。因此可以放心大胆的交给本地储存管理,通过 localStorage 储存到本地,这样即使页面刷新,窗口重启也会拿到之前的搜索记录。
本地储存优化
合理的使用(缓存+本地储存)搭配(路由传参+接口请求)结合(状态管理)似乎已经解决了绝大部分的业务通信场景所遇到的问题了。更多的诸如 WebSocket 之类的暂时不做探讨。
对本地储存而言,什么场景用?怎么去用?其实都是需要注意或者说是需要优化的点。
到店 H5 项目框架的编写者中对本地储存进行了封装,主要的优化点如下:
- 使用 namespace 模式解决全局环境污染
- 使用 MD5 加密,保证数据的完整性
- 封装类型判断和 json 序列化达到储存 ts 引用类型数据
怎么去用
不要直接使用 localStorage.setItem 之类的 api,将本地储存进行封装后再暴露出去,
主要就是避免环境变量的污染和数据被篡改时,不会稀里糊涂。
class PageModel extends LifeCycle<Params, Query> {
/**
* 定义菜品搜索localStorage
*/
private static storage = new Storage<{ HISTORYDATA: Array<string> }>(
"historyDishes",
{ HISTORYDATA: "" },
localStorage
);
PageModel.storage.setItem("HISTORYDATA", this.historyData);
}
什么场景用
结合框架编写者给出的建议,我感觉可以主要运用于以下地方:
- history 的详细记录:避免 history 出于安全性的考虑对浏览历史记录的限制;
- 充当临时 form:保存用户填了一半的数据;
- 存个人信息:非关键信息,主要用于 ui 展示
- 用户搜索记录:用于快捷搜索
参考资料:
到店 H5 项目
关于网页本地存储的一些思考
本地存储和离线缓存的作用和区别
深入理解浏览器的缓存机制
——————————————————————————感谢咱们组的小伙伴开发出了一个优秀的 H5 框架,可以让我不断的深入学习
最后
以上就是缓慢时光为你收集整理的本地存储解决方案思考关于 H5 项目中本地储存机制的思考的全部内容,希望文章能够帮你解决本地存储解决方案思考关于 H5 项目中本地储存机制的思考所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复