网站首页 > 开源技术 正文
在做项目的过程中,我们经常遇到需要把信息存储在本地的情况,比如权限验证的token、用户信息、埋点计数、客户配置的皮肤信息或语言种类等,我们可以暂存一下避免浏览器不必要的请求和客户多余操作,给客户使用带来方便。
上一篇讲了JavaScript浏览器端数据存储方案之Cookie篇,这篇文章主要介绍localStorage和sessionStorage。
HTML5中 Web Storage 的出现,主要是为了弥补使用 Cookie 作为本地存储的不足。Cookie 存储的数据量非常小,而且数据会自动携带到请求头里,但服务器端可能并不关心这些数据,所以会造成带宽的浪费。
Web Storage 提供了两个存储对象:localStorage 和 sessionStorage。
sessionStorage 存储的数据仅在本次会话有用,会话结束后会自动失效,而且数据仅在当前窗口有效,同一源下新窗口也访问不到其他窗口基于sessionStorage 存储的数据。也是由于这些特性,导致 sessionStorage 的使用场景会比较少。
localStorage 可以永久存储,而且同源下数据多窗口也能共享。看起来很美好,但 localStorage 也有短板,绝大多数浏览器有 5M 的大小限制。但是这不足以成为大家使用 localStorage 的障碍,要知道 Cookie 只有 4K 的大小,多了一千多倍
localStorage 的基本使用
localStorage.setItem("b","isaac");//设置b为"isaac" var b = localStorage.getItem("b");//获取b的值,为"isaac" var a = localStorage.key(0); // 获取第0个数据项的键名,此处即为“b” localStorage.removeItem("b");//清除c的值 localStorage.clear();//清除当前域名下的所有localstorage数据
这里和大家分享一段我们在VUE项目中封装使用的localStorage,大家可以借鉴实现的思路
有两点需要注意一下。在 setItem 时,可能会达到大小限制,最好加上错误捕捉
另外在存储容量快满时,会造成 getItem 性能急剧下降。我们下面看看 localStorage 有哪些脑洞大开的用法
缓存静态文件
你不禁要问,HTTP 协议不是本来就支持缓存文件吗,为什么还要使用 localStorage 来缓存?为了可编程化,通俗一点说就是把命运握在自己手中。
HTTP 协议的缓存,可以由用户浏览器清除或禁用缓存,也可以由 Web 服务器设置过期时间或不缓存。对于前端工程师,这更像是一个黑盒,想要决定文件是访问缓存还是访问远程显得有些力不从心了。
使用 localStorage 控制文件缓存的方式有两种:
- 使用 Loader 加载静态文件
- 借助服务器端将静态文件 inline 化
这两种方式一般都会提前做好缓存过期策略,通常是使用版本号来控制,下面还会细讲。否则文件新版上线,用户客户端还是旧版,这就麻烦大了,而且这类问题,还不好调试不好重现。
使用 Loader 加载静态文件
由于请求都是动态发出的,所以可以对请求拦截处理。大致流程如下:
- 查看请求的文件 url 是否有缓存到 localStorage
- 如果没有,到第 2 大步
- 如果有,判断文件是否过期或版本号是否匹配
- 过期或不匹配,到第 2 大步
- 文件内容有效,到第 4 大步
- 请求远程文件
- 缓存最新文件内容
- 执行文件内容
这个方式有个开源库:basket.js(可以在github上访问)
借助服务器端将静态文件 inline 化
这个方式比上面那种更进一步,在第一次响应时把需要放入 localStorage 的文件都内联进 html 中,后面每次响应只要文件版本没有变化,都是渲染一段从 localStorage 加载该文件的代码。这样做的好处是可以有效减少请求次数,即使是第一次。
版本号不匹配(版本号可记在 Cookie 中,第一次访问没有版本号),服务端响应内容:
<script> function script2ls(id) { var script = document.getElementById(id); if (script) { localStorage[id] = script.innerHTML; } } </script> <script id="jquery.js">...jquery source code...</script> <script>script2ls('jquery.js')</script>
版本号匹配,服务端响应内容:
<script> function ls2script(id) { var script = document.createElement('script'); script.text = localStorage[id]; document.head.appendChild(script); } </script> <script>ls2script('jquery.js')</script>
不过使用 localStorage 缓存文件会有 XSS 的风险,而且造成的伤害可能是永久的
同源窗口通信
你可能不禁又要问,不是有 postMessage 吗?没错 postMessage 确实可以用于窗口或 iframe 间通信,但是前提是你必须拿到打开新窗或 iframe 的句柄对象:
var popup = window.open(...popup details...); popup.postMessage("hello there!", "http://example.com");
这样在新窗中再打开新窗,似乎就不好传递消息了。
你可能还想问,为什么要在窗口间通信?好问题,没有应用场景的技术都是耍流氓。像多窗口共用的一些组件,而且对数据实时同步都有较高要求的都会是这个技术的应用场景。比如通知中心上面的未读数量,两个窗口,A 窗口更新为 8,切到 B 窗口还是 9,这就造成了体验不一致,这个例子可能还觉得无关痛痒;再比如购物车,两个产品窗口,A 窗口添加到购物车,切到 B 窗口添加到购物车,发现没有 A 添加的产品,这样就比较严重了。这当然也可以通过每个窗口都与后台建立连接来更新,但用户如果开十几个窗口就开销大了。
有了同源窗口通信,我们就可以只有一个窗口与后台建立连接,收到更新后,广播给其他窗口就可以。说了这么多,实现原理是怎样的呢?
其实原理也简单,每次 localStorage 中有任何变动都会触发一个 storage 事件,所有窗口都监听这个事件,一旦有窗口更新 localStorage,其他窗口都会收到通知,根据事件中的 key 把不关心的变动过滤掉。原理是很简单,但是要实现一套完整的广播机制还是有些复杂,你需要:
- 管理好每个窗口的唯一 ID
- 防止消息重复
- 防止消息发给不关心的窗口
- 窗口心跳 keep alive
- 主窗口选举
- ...
不用担心,已经有了不错的开源实现:diy/intercom.js、tejacques/crosstab
作为前端 DB 的存储介质
你可能不满足于用键值对保存数据,你还想保存更复杂的数据结构。
灵活存取 json 格式的数据:typicode/lowdb
通过 sql 对数据 CURD 操作:agershun/alasql
表单自动持久化
在填写表单时,遇到浏览器奔溃或者误操作导致填写内容丢失,此刻用户的内心也应该是奔溃的。误操作还可以加一个 beforeunload 事件,在关闭浏览器或跳出当前页前提醒一下用户。那浏览器崩溃呢,将数据变更实时保存到后台,这样似乎开销很大,实时保存到 localStorage 是个不错的解决方案,真巧,也有一个开源实现:simsalabim/sisyphus
猜你喜欢
- 2024-10-23 酒吧舞台经营者必看 专业功放知识
- 2024-10-23 专业科普丨「足底筋膜炎」,看这一篇文章就够了
- 2024-10-23 600美元的GE智能洗碗机 纯不锈钢材质再无塑料Low感
- 2024-10-23 FL Studio的EQ调试方法(二)(fl studio eq自动化)
- 2024-10-23 调音台分类及介绍(调音台分为哪三类)
- 2024-10-23 万魔SonoFlow降噪蓝耳机评测:好音质,强降噪,长续航,真舒适
- 2024-10-23 万魔首款头戴降噪耳机 SonoFlow 发布:双金标认证,499 元
- 2024-10-23 运算放大器原理(运算放大器原理图的封装)
- 2024-10-23 Javascript本地存储 cookie sessionStorage localStorage indexedDB
- 2024-10-23 基于Electron开发Hosts切换工具的“踩坑”之旅
你 发表评论:
欢迎- 05-08Peking Opera Featuring National Treasure Min Fanglei Premiers in Changsha
- 05-08安卓版Opera Mini浏览器更新,增强大屏设备支持
- 05-08Opera 36.0开发者版本发布:个性化新闻+简化菜单
- 05-08Vitas发布20周年专辑《OPERA20》首支单曲
- 05-08Android 版 Opera 89 带来了大量标签页改进
- 05-08基本Spring Cloud的微服务架构搭建及应用(一)
- 05-08代码质量扫描工具SonarQube原理及环境搭建
- 05-08小心!你的这些习惯和粗心,可能正在泄露信息!丨提示
- 最近发表
-
- Peking Opera Featuring National Treasure Min Fanglei Premiers in Changsha
- 安卓版Opera Mini浏览器更新,增强大屏设备支持
- Opera 36.0开发者版本发布:个性化新闻+简化菜单
- Vitas发布20周年专辑《OPERA20》首支单曲
- Android 版 Opera 89 带来了大量标签页改进
- 基本Spring Cloud的微服务架构搭建及应用(一)
- 代码质量扫描工具SonarQube原理及环境搭建
- 小心!你的这些习惯和粗心,可能正在泄露信息!丨提示
- 一步步搭建openwrt编译环境并编译ddserver源码
- 远程办公、巡逻机器人、口罩识别……离不开一群“研发技术宅”
- 标签列表
-
- jdk (81)
- putty (66)
- rufus (78)
- 内网穿透 (89)
- okhttp (70)
- powertoys (74)
- windowsterminal (81)
- netcat (65)
- ghostscript (65)
- veracrypt (65)
- asp.netcore (70)
- wrk (67)
- aspose.words (80)
- itk (80)
- ajaxfileupload.js (66)
- sqlhelper (67)
- express.js (67)
- phpmailer (67)
- xjar (70)
- redisclient (78)
- wakeonlan (66)
- tinygo (85)
- startbbs (72)
- webftp (82)
- vsvim (79)
本文暂时没有评论,来添加一个吧(●'◡'●)