html5 storage api

localStoragesessionStoragehtml5 新增的用来存储数据的对象,他们让我们可以以键值对的形式存储信息。

为什么要有 storage ?

我们已经有了 session 可以帮助我们存储信息,为何还需要 storage 呢?

  1. 各个浏览器的 cookie 长度大概只能在 4kb 左右,而 storage 大概能达到 5M,这意味着可以存储更多的信息
  2. cookie 可以被后端更改,在每次进行网络请求的时候都会被发送给服务器,而 storage 不会,这意味着这个存储是完全受控于前端(JavaScript)的。

storage 类型

storage 一共有两种

  1. localStorage

    这个存储对象的存储和 origin 有关,即只要是同域名同协议同端口,存储是共享的。尽管关机了,或是关掉浏览器了,只要打开同源网站,存储的数据会依然存在,数据不会过期消失。

  2. sessionStorage

    这个存储对象的存储是暂时的,只保持在当前会话中,简单来说就是和浏览器的一个 tab 有关,只要 tab 关掉了再打开数据就没了,但是在当前界面刷新的话,数据就还在(这个时候认为是一个 tab)。

两个 storageapi 很相似,下面以 localStorage 为例

localStorage 演示

基础 api

localStorage.setItem("name", "huro"); // 设置键值对

可以在 chrome 浏览器的控制台进行观察,这里已经设置上去了。下面也可以做相应的测试。

localStorage.getItem("name"); // huro
localStorage.removeItem("name"); // 删除某个键
localStorage.clear(); // 删除所有键值对
localStorage.key(0); // 获得索引为 0 的key
localStorage.length; // 获得 `localStroage` 的键的个数

以上是 storageapi

唯一需要注意的是 key(index) 这个 apikey 被设置的先后是没有关系的。

类对象操作

也可以用类对象的方法操作

localStorage.name = "huro";
console.log(localStorage.name); // huro
delete localStorage.name; // 删除键

但是上面的做法不推荐,如果用的是某些特殊的 key 例如 length 就会报错,因为原先 localStorage.length 表示获得键值对长度,理应是不能修改的。

localStorage["length"] = 4; // 修改无效

因此不推荐用这个做法修改 storage

遍历键值

由于 storage 并没有 Symbol.iterator 属性,这意味着 storage 不能用 for of循环遍历。以下有三种遍历方式。

假设我们只有一个键值对 name: huro

  1. for in 循环
for (let key in localStorage) {
console.log(key);
}

上述的写法是错误的,因为 for in 循环会遍历原型链上的属性和方法,因此需要稍作改善。

for (let key in localStorage) {
if (!localStorage.hasOwnProperty(key)) {
continue;
}
console.log(key);
}

这个时候就能正确的只打印出键 name

  1. 简单 for 循环
for(let i = 0; i < localStorage.length; i+= 1) {
let key = localStorage.key(i);
console.log(key);
}

这个时候能正确的只打印出键 name

  1. Object.keys()

这个方法会获得某个对象自身的 key,而不会管原型链上的

const keys = Object.keys(localStorage);
for(let key of keys) {
alert(key);
}

而且获得的 key 是数组,具有 iterator 因此可以用 for of 遍历

这个时候能正确的只打印出键 name

只能是 string

storage 被设计出来比较不足的地方是,键和值都只能是 string 类型的,如果不是的话,会自动转换成 string

由于是隐式转换,初学者往往不知道,这意味着可能带来一些 bug

localStorage.user = { name: "huro" };
console.log(localStorage.user); // [object Object]

上述代码在存储 user 的时候,被自动调用 toString 方法,转化为了 [object Object]

storage 事件

storage 事件返回一个对象,里面包含几个参数

  1. key 改变的键
  2. oldValue => 旧值 || null
  3. newValue => 新值 || null
  4. url 触发这个事件的 url 地址
  5. storageArea 要么是 localStorage 要么是 sessionStorage 取决与是更改哪个storage
// 1.html
window.addEventListener("storage", (state) => {
console.log(state.key, state.value, state.url); // name huro ./2.html(实际 url 是绝对路径)
}) // 2.html
localStorage.setItem("name", "huro");

还记得我们之前说过, localStorage 只要是同源都可以分享吗,这意味如果我们打开了两个窗口,只要他们是同源的,我们可以用上述的监听事件,监听另一个端口修改 storage,也就是可以实现不同的窗口之间的数据共享。

注意: 经测试,chrome edge 等现代浏览器不会触发自身文件或同文件的 storage 事件,即必须是两个不同的 html 才会互相触发。

例如 test1.htmltest2.html 都设置了 storage 监听事件,且同源。

test1.htmlstorageapi 事件会触发 test2.html 的,但是不能触发本身的 storage 监听事件。

另外这里的 api 事件也有限制,经过笔者测试,似乎只有

  1. setItem
  2. getItem
  3. removeItem

有效果,而 clear 事件是没有效果的。

上面全程用 localStorage 演示,

sessionStorage 也是类似的,读者有兴趣可以自行码一下代码。

总结

storage 是很好的一个 html5 特性,让我们方便快捷的存储数据,美中不足的是只能存储字符型数据,不过也很容易解决这个问题。同时利用监听事件,也可以实现不同窗口之间的广播机制。是非常实用的一个特性。

一篇文章图文并茂地带你轻松学会 HTML5 storage的更多相关文章

  1. 一篇文章图文并茂地带你轻松实践 HTML5 history api

    HTML5 history api 前言 由于笔者在网络上没有找到比较好的关于 history api 的实践案例,有的案例过于杂乱,没有重点,有些案例只是告诉读者 api 是什么,却没告诉怎么用,本 ...

  2. 一篇文章图文并茂地带你轻松学完 JavaScript 设计模式(一)

    JavaScript 设计模式(一) 本文需要读者至少拥有基础的 ES6 知识,包括 Proxy, Reflect 以及 Generator 函数等. 至于这次为什么分了两篇文章,有损传统以及标题的正 ...

  3. 一篇文章图文并茂地带你轻松学完 JavaScript 设计模式(二)

    JavaScript 设计模式(二) 本篇文章是 JavaScript 设计模式的第二篇文章,如果没有看过我上篇文章的读者,可以先看完 上篇文章 后再看这篇文章,当然两篇文章并没有过多的依赖性. 5. ...

  4. 一篇文章图文并茂地带你轻松学完 JavaScript 事件循环机制(event loop)

    JavaScript 事件循环机制 (event loop) 本篇文章已经默认你有了基础的 ES6 和 javascript语法 知识. 本篇文章比较细致,如果已经对同步异步,单线程等概念比较熟悉的读 ...

  5. 一篇文章图文并茂地带你轻松学完 JavaScript 继承

    JavaScript 继承 在阅读本文章之前,已经默认你了解了基础的 JavaScript 语法知识,基础的 ES6 语法知识 . 继承种类 简单的继承种类可以分为 构造函数继承 原型链继承 clas ...

  6. 一篇文章图文并茂地带你轻松学完 JavaScript 原型和原型链

    JavaScript 原型和原型链 在阅读本文章之前,已经默认你了解了基础的 JavaScript 语法知识,基础的 ES6 语法知识 . 本篇文章旨在为 JavaScript继承 打下基础 原型 在 ...

  7. 一篇文章图文并茂地带你轻松学完 JavaScript 闭包

    JavaScript 闭包 为了更好地理解 JavaScript 闭包,笔者将先从 JavaScript 执行上下文以及 JavaScript 作用域开始写起,如果读者对这方面已经了解了,可以直接跳过 ...

  8. 一篇文章让Oracle程序猿学会MySql【未完待续】

    一篇文章让Oracle DB学会MySql[未完待续] 随笔前言: 本篇文章是针对已经能够熟练使用Oracle数据库的DB所写的快速学会MySql,为什么敢这么说,是因为本人认为Oracle在功能性方 ...

  9. 一篇文章教你学会ASP.Net Core LINQ基本操作

    一篇文章教你学会ASP.Net Core LINQ基本操作 为什么要使用LINQ LINQ中提供了很多集合的扩展方法,配合lambda能简化数据处理. 例如我们想要找出一个IEnumerable< ...

随机推荐

  1. ASP.NET Core错误处理中间件[4]: 响应状态码页面

    StatusCodePagesMiddleware中间件与ExceptionHandlerMiddleware中间件类似,它们都是在后续请求处理过程中"出错"的情况下利用一个错误处 ...

  2. Docker 建站小记

    一,前言 Docker 建站小记,我使用了四个镜像来搭建:nginx,certbot,mysql,gradle.欢迎访问:https://www.zzk0.top 这个网页是从 github 上找的个 ...

  3. SQL Server 2012 忘记sa用户处理方法

    SQL Server 2012 忘记sa用户的密码,可重置sa密码,方法如下: 1.将身份验证改成Windows身份验证,登录进去 2.进入SQL Server控制台,在对象资源管理器中找到Secur ...

  4. cfsetispeed、cfsetospeed和cfsetspeed探究

    在我https://www.cnblogs.com/Suzkfly/p/11055532.html这篇博客中有一个疑问,就是在串口设置波特率的域中,没有将输入输出波特率分开,那为什么会有几个不同的设置 ...

  5. Redis 实战 —— 07. 复制、处理故障、事务及性能优化

    复制简介 P61 关系型数据库通常会使用一个主服务器 (master) 向多个从服务器 (slave) 发送更新,并使用从服务器来处理所有读请求. Redis 也采用了同样的方法实现自己的复制特性,并 ...

  6. 2021/1/20随记,MTU

    背景: 事情是这样的,客户2台防火墙部署了ipsec,内网互通,但是其中ssh以及其他大命令之类的操作就会卡住,简单的vi命令可以使用. 解决: 排除网络问题,因为内网互通,其次是系统层面问题,最终定 ...

  7. Python+Selenium+Unittest实现PO模式web自动化框架(7)

    1.TestDatas目录的功能 TestDatas目录下存放的是测试数据,比如:登录功能的测试用例数据. # --^_^-- coding:utf-8 --^_^-- # @Remark:登录测试数 ...

  8. 接口新建学习---cookie策略

    一.为什么要添加cookie? 模拟浏览器,因为http是无状态协议,像览器一样的存储和发送Cookie,如果发送一个http请求他的响应中包含Cookie,那么Cookie Manager就会自动地 ...

  9. ValueError: the environment variable is longer than 32767 characters On Windows, an environment variable string ("name=value" string) is limited to 32,767 characters

    https://github.com/python/cpython/blob/aa1b8a168d8b8dc1dfc426364b7b664501302958/Lib/test/test_os.py ...

  10. 请不要继续将数据库称为 CP 或 AP - 掘金 https://juejin.im/post/6844903878102614030

    请不要继续将数据库称为 CP 或 AP - 掘金 https://juejin.im/post/6844903878102614030