百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

localStorage 多种使用方法

toyiye 2024-06-21 12:42 10 浏览 0 评论

HTML5中 Web Storage 的出现,主要是为了弥补使用 Cookie 作为本地存储的不足。Cookie 存储的数据量非常小,而且数据会自动携带到请求头里,但服务器端可能并不关心这些数据,所以会造成带宽的浪费。

Web Storage 提供了两个存储对象:localStorage 和 sessionStorage。

sessionStorage 存储的数据仅在本次会话有用,会话结束后会自动失效,而且数据仅在当前窗口有效,同一源下新窗口也访问不到其他窗口基于

sessionStorage 存储的数据。也是由于这些特性,导致 sessionStorage 的使用场景会比较少。

localStorage 可以永久存储,而且同源下数据多窗口也能共享。看起来很美好,但 localStorage 也有短板,绝大多数浏览器有 5M 的大小限制。但是这不足以成为大家使用 localStorage 的障碍,要知道 Cookie 只有 4K 的大小,多了一千多倍,偷着乐吧。

localStorage 的基本使用

讲这个内容的文章网上太多了,现在再来讲有点老套了。这里就不做更多介绍了,不清楚的读者可以看 这里

有两点需要注意一下。在 setItem 时,可能会达到大小限制,最好加上错误捕捉

try {
  localStorage.setItem(key, value);
} catch(e) {
  if (isQuotaExceeded(e)) {
    // Storage full, maybe notify user or do some clean-up
  }
}

function isQuotaExceeded(e) {
  var quotaExceeded = false;
  if (e) {
    if (e.code) {
      switch (e.code) {
        case 22:
          quotaExceeded = true;
          break;
        case 1014:
          // Firefox
          if (e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
            quotaExceeded = true;
          }
          break;
      }
    } else if (e.number === -2147024882) {
      // Internet Explorer 8
      quotaExceeded = true;
    }
  }
  return quotaExceeded;
}

另外在存储容量快满时,会造成 getItem 性能急剧下降

我们下面看看 localStorage 有哪些脑洞大开的用法。

缓存静态文件

你不禁要问,HTTP 协议不是本来就支持缓存文件吗(之前写过一篇文章 《Web缓存之HTTP指南》 ),为什么还要使用 localStorage 来缓存?为了可编程化,通俗一点说就是把命运握在自己手中。

HTTP 协议的缓存,可以由用户浏览器清除或禁用缓存,也可以由 Web 服务器设置过期时间或不缓存。对于前端工程师,这更像是一个黑盒,想要决定文件是访问缓存还是访问远程显得有些力不从心了。

使用 localStorage 控制文件缓存的方式有两种:

  1. 使用 Loader 加载静态文件
  2. 借助服务器端将静态文件 inline 化

这两种方式一般都会提前做好缓存过期策略,通常是使用版本号来控制,下面还会细讲。否则文件新版上线,用户客户端还是旧版,这就麻烦大了,而且这类问题,还不好调试不好重现。

使用 Loader 加载静态文件

由于请求都是动态发出的,所以可以对请求拦截处理。大致流程如下:

  1. 查看请求的文件 url 是否有缓存到 localStorage如果没有,到第 2 大步如果有,判断文件是否过期或版本号是否匹配过期或不匹配,到第 2 大步文件内容有效,到第 4 大步
  2. 请求远程文件
  3. 缓存最新文件内容
  4. 执行文件内容

这个方式有个开源库: basket.js

借助服务器端将静态文件 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>

同源窗口通信

你可能不禁又要问,不是有 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.jstejacques/crosstab

其他

作为前端 DB 的存储介质

你可能不满足于用键值对保存数据,你还想保存更复杂的数据结构。

灵活存取 json 格式的数据: typicode/lowdb

通过 sql 对数据 CURD 操作: agershun/alasql

表单自动持久化

在填写表单时,遇到浏览器崩溃或者误操作导致填写内容丢失,此刻用户的内心也应该是崩溃的。误操作还可以加一个 beforeunload 事件,在关闭浏览器或跳出当前页前提醒一下用户。那浏览器崩溃呢,将数据变更实时保存到后台,这样似乎开销很大,实时保存到 localStorage 是个不错的解决方案,真巧,也有一个开源实现: simsalabim/sisyphus

总结

文件缓存现在有更好的解决方案,没错,说的就是 Service Worker 的 CacheStorage

不过多了解一些脑洞大开的想法,有利于拓展解决问题的思路。

Enjoy open source :heart:

参考:

1: Always catch LocalStorage security and quota exceeded errors

2: Measuring localStorage Performance

3: 使用 SRI 增强 localStorage 代码安全

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码