HTML Web Storage


浅谈 Web 前端 Client side storage。更新参考这篇An Overview of Client-Side Storage

目前有四种 active 的方式:Cookies,Local Storage,Session Storage,IndexedDB。

Cookies

Cookies 是一种经典地存储简单 string 数据的方式。可以由 server 发给 client,然后 client 保存在本地,下次请求再传回 server。这样 server 可以管理帐户 session,追踪用户信息。它可以由 client 本地设置,传给 server。

以前也用它来存储纯客户端的数据,比如用户偏好。具体操作见 JS BOM 章节 Cookies 部分。

优势:

  1. 可用于与 server 的通信
  2. 可设置自动过期时间,不需要手动删除

劣势:

  1. 存储数据量小(大约4KB多数据)
  2. 只能存 string
  3. 潜在安全问题Cookies and security
  4. 自从 Web Storage API 出来它不再是推荐的客户端存储方法

Local Storage

window.localStorage 是 H5 Web Storage API 之一,区别于 Cookies,存储的数据不会发给 server,可以被同源的每个窗口或标签页共享。

window interface 提供的只读属性,允许获取文档 origin 下的 Storage 对象。

存储的数据不会因为浏览器关闭而删除,如没有干预,将一直有效。

注意:如果用户使用 “无痕/私有/隐私保护” 模式的进行浏览,那么在浏览器关闭后,localStorage 中的值将不会保存。因为使用了这种模式的用户已经明确选择不留痕迹

操作方法:

const user = { name: 'Vivienne', age: 25 }

// Create
localStorage.setItem('user', JSON.stringify(user));

// Read (Single)
JSON.parse(localStorage.getItem('user'))
// 如果 key 不存在,返回 null

// 也可以使用以下方法 create/read
localStorage.lastname = "Smith";
localStorage['lastname'] = "Smith";

// Update
const updatedUser = { name: 'Vivienne', age: 24 }
localStorage.setItem('user', JSON.stringify(updatedUser));

// Delete
localStorage.removeItem('user');

// 获取所有key名
Object.keys(localStorage)

优势:与 Cookies 对比

  1. 更简单直观地操作接口
  2. 更安全(数据不会在网络上传输)
  3. 存储更多数据(至少5MB)

劣势:

只允许存储 String,但我们可以存储 stringified JSON,实现存储复杂数据。

区别: http 和 https 相同域名下的 localStorage 数据不共享,而 cookie 是共享的。

注意!!!网站通过 http://example.com 加载返回的 local storage 对象与 通过 https://example.com 加载不同。

Session Storage

window.sessionStorage 是 H5 Web Storage API 第二种类型,用法、优劣势、支持性都同 localStorage。区别:数据只为 browser tab session 存储(即数据只在构建它们的窗口或标签内可见)。

补充:

  • clear() 函数删除存储列表中所有的数据,空的 Storage 对象调用此函数也是安全的,只是不执行任何操作。
  • 如果用户已关闭了网站的存储,或存储达到其最大的容量,此时设置数据将抛出 QUOTA_EXCEEDED_ERR 错误。
  • 只要有同源的 Storage 事件发生(包括 SessionStorage 和 LocalStorage 触发的事件),已注册的所有事件侦听器作为事件处理程序就会接到相应的 Storage 事件。该事件中包含与存储变化有关的信息。如果是新添加的数据,则 oldValue 属性值为 null;如果是被删除的数据,则 newValue 属性值为 null
  • 打开多个相同URL的标签页,每个标签页创建各自的 sessionStorage 对象。关闭对应标签页,会清除该标签页的 sessionStorage 对象。

IndexedDB

IndexedDB 是一个事务型基于 JavaScript 的面向对象数据库,用于在客户端存储大量的结构化数据(也包括文件/二进制大型对象(blobs))。只需要指定数据库模式,打开与数据库的连接,然后检索和更新一系列事务

  • 该 API 可以存储结构化克隆算法支持的任何对象。
  • 使用索引实现对数据的高性能搜索。
  • 操作是异步执行。
  • 遵守同源策略。

优势:

  1. 可处理更复杂、结构化的数据
  2. 可拥有多个 databases,每个数据库里可有多个 tables
  3. 存储更多数据
  4. 更多交互上的控制

劣势:

相比 Web Storage API 用起来复杂。如果你更喜欢一个简单的 API,可以考虑使用第三方库。

同源策略

目的:保证用户信息的安全,防止恶意网站窃取数据。

协议、主域名、子域名和端口号都相同,则为同源。

有三种行为受到同源策略限制:

  • Cookie、LocalStorage 和 IndexedDB 无法读取。
  • DOM 无法获得。
  • AJAX 请求无法发送。

但一个网站很难掌握所有的资源,因此就需要跨域访问:

  1. CORS(Cross-Origin Resource Sharing):允许服务器设置 Access-Control-Allow-Origin 头,允许跨域请求。

    主要应用三种场景:简单请求(GET、HEAD、POST,头部字段仅包含Accept、Accept-Language、Content-Language、Content-Type,其中Content-Type的值仅限于这3者之一:application/x-www-form-urlencoded、multipart/form-data、text/plain)、预检请求(PUT、DELETE、OPTIONS等,可以自定义头部,向服务器发送application/json格式的数据)、认证请求。 预检请求:在正式请求之前,客户端发送一个 OPTIONS 请求,询问服务器是否允许跨域请求。服务器成功响应后,返回 Access-Control-Allow-Methods 头,客户端再发送实际请求。

  2. JSONP(JSON with Padding):通过动态创建 script 标签,请求跨域资源,并在请求成功后执行回调函数。参看JavaScript JSON章节。