找回密码
 立即注册
首页 业界区 业界 Web前端入门第 84 问:JavaScript sessionStorage 那些 ...

Web前端入门第 84 问:JavaScript sessionStorage 那些容易踩坑的地方

蟠鲤 6 天前
sessionStorage 与 localStorage 差不多可以算作一对兄弟,它俩的暴露的 API 方法一模一样。
但两者也有不同点:
1、sessionStorage 存入的数据在页面关闭后,会自动清除。
2、相同 URL 的每个 tab 页签的 sessionStorage 会被隔离,互不影响。也就是说相同的链接,在 A 标签页打开和在 B 标签打开,A 写入的 sessionStorage 数据,B 是无法读取的!!这里与 会话 Cookie 完全不一样。
3、在页面中使用  和 window.open 打开新的标签页,sessionStorage 数据会复制,但之后的修改相互隔离。
4、sessionStorage 存入的数据会在浏览器打开期间一直保留,刷新页面或使用 ctrl + shift + t 恢复页面时,数据不会丢失。
API

sessionStorage 暴露的接口与 localStorage 一致:
  1. // 只读属性,返回会话存储项的数目
  2. sessionStorage.length
  3. // 获取会话存储的第 n 个键名
  4. sessionStorage.key(n)
  5. // 获取会话存储的值
  6. sessionStorage.getItem(key)
  7. // 写入会话存储
  8. sessionStorage.setItem(key, value)
  9. // 删除会话存储
  10. sessionStorage.removeItem(key)
  11. // 清空所有会话存储
  12. sessionStorage.clear()
复制代码
API 使用示例:
  1. (() => {
  2.   // 写入数据
  3.   sessionStorage.setItem('type', '公众号');
  4.   sessionStorage.setItem('name', '前端路引');
  5.   // 获取会话存储长度
  6.   console.log(sessionStorage.length);
  7.   // 循环打印会话存储
  8.   for (let i = 0; i < sessionStorage.length; i++) {
  9.     const key = sessionStorage.key(i);
  10.     const value = sessionStorage.getItem(key);
  11.     console.log(`${key}: ${value}`);
  12.   }
  13.   // 移除单个会话存储
  14.   sessionStorage.removeItem('name');
  15.   // 移除所有会话存储
  16.   sessionStorage.clear();
  17. })()
复制代码
无法监听存储数据变化

不像 localStorage,sessionStorage 没有暴露 onchange 事件,所以无法监听到数据变化,就算模拟自定义事件,也只能在当前页面中获得事件,无法跨页面通信。以下代码只能在本页面中监听 sessionStorage 数据改变:
  1. (() => {
  2.   // 移除所有会话存储
  3.   sessionStorage.clear();
  4.   
  5.   // 监听 storage 事件
  6.   window.addEventListener('storage', e => {
  7.     console.log(e);
  8.   })
  9.   // 自定义写入函数,封装事件派发
  10.   function setItem (key, value) {
  11.     // 模拟 storage 事件
  12.     const ev = new StorageEvent('storage', {
  13.       key,
  14.       newValue: value,
  15.       oldValue: sessionStorage.getItem(key),
  16.       url: location.href,
  17.     });
  18.     window.dispatchEvent(ev);
  19.     sessionStorage.setItem(key, value);
  20.   }
  21.   setItem('type', '公众号');
  22.   setItem('name', '前端路引');
  23. })()
复制代码
测试结果:
1.png

新开页面复制 sessionStorage

在 a 标签中添加 rel="opener" 可令新开的页面获得父页面中的 sessionStorage 数据(复制方式)。
window.open 方法打开的页面也是一样的道理。
注意:此时获得数据仅仅是副本,不共享,所以在新页面或旧页面中修改数据时,两者互不影响。
a 标签默认是 noopener,如果不显示设置 rel="opener",无法获得数据副本!!
测试代码:
  1. a 标签打开本页面

  2. a 标签 opener 打开本页面

  3. a 标签 noopener 打开本页面

  4. <button
  5.   onclick="window.open('./example-84-3.html')"
  6. >window.open 打开本页面</button>

  7. <button
  8.   onclick="window.open('./example-84-3.html', '_blank', 'noopener')"
  9. >window.open noopener 打开本页面</button>

  10. <button id="set">写入新的 sessionStorage</button>

  11. <button id="get">获取 sessionStorage</button>
复制代码
测试结果:
2.gif

大小限制

与 localStorage 一样限制 5MB 大小(所有键值加在一起的长度),溢出后写入报错,此处推荐阅读前一篇文章:{%post_link 'wechat-web-front-end-83'%}
测试代码:
  1. (() => {
  2.   // 移除所有会话存储
  3.   sessionStorage.clear();
  4.   const key = 'name';
  5.   const max = 5 * 1024 * 1024;
  6.   // 测试极限值
  7.   // const value = 'a'.repeat(max - key.length);
  8.   // 测试中文
  9.   // const value = '中'.repeat(max - key.length);
  10.   // 测试溢出
  11.   const value = 'a'.repeat(max - key.length + 1);
  12.   sessionStorage.setItem(key, value);
  13.   // 测试多个项溢出情况
  14.   // sessionStorage.setItem('key', '1');
  15.   // 测试与 localStorage 是否共用存储空间
  16.   // localStorage.setItem('key', '1');
  17. })()
复制代码
溢出结果:
3.png

结论:setItem 多个子项时,公用 5MB 存储空间(中英文计算方式一致),溢出时写入报错,并且与 localStorage 不共用存储空间!使用 rel="opener" 打开链接时,会获得父页面的副本数据,所以新开的页面仅能写入 5MB - 副本数据 等到的剩下空间。
可使用以下代码判断是否拥有副本数据:
  1. if (window.opener) {
  2.   // opener 存在表示拥有副本
  3.   // 极限情况再写入新的数据报错
  4.   sessionStorage.setItem('now', Date.now());
  5. }
复制代码
刷新与恢复页面

页面刷新时和关闭页面后再使用 ctrl+shift+t 恢复页面,sessionStorage 数据不会丢失。
测试代码:
  1. <button id="set">写入新的 sessionStorage</button>

  2. <button id="get">获取 sessionStorage</button>
复制代码
效果:
4.gif

写在最后

sessionStorage 仅支持字符串存储,所以 JS 中用的 JSON 数据需要格式化为字符串存储~~
sessionStorage 一般多用于临时数据存储,比如一些表单填写的临时数据,单页应用页面间的数据传递等。
其生命周期有点短暂,浏览器或标签页关闭就会消失,就像浮游一样,朝生暮死...

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册