DOM 存储简介
DOM 存储 API 包含两种使用文档对象模型 (DOM) 以安全方式保留客户端数据的相关机制,即 sessionStorage 和 localStorage。 Internet Explorer 8 中引入了这些对象。
注意 对于以前版本的 Internet Explorer,持久数据存储是由 userData 行为实现的。
本主题包含以下各部分。
- 什么是 DOM 存储?
- DOM 存储脚本编写对象
- window.sessionStorage
- window.localStorage
- Storage 对象
- DOM 存储事件
- onstorage
- onstoragecommit
- 安全和隐私
- 顶层浏览上下文和源
- 源确定存储限制
- 清除存储区域
- 相关主题
什么是 DOM 存储?
人们经常会将 DOM 存储比作 HTTP Cookie。 与 Cookie 类似,Web 开发人员可以使用 DOM 存储,将每个会话或特定于域的数据作为名称/值对存储在客户端上。 不过,与 Cookie 不同的是,使用 DOM 存储更易于控制由一个窗口存储的信息如何显示在另一个窗口中。
例如,某个用户可能会打开两个浏览器窗口来购买两张不同航班的机票。 但是,如果航空公司的 Web 应用程序使用 Cookie 来存储其会话状态,则信息可以从一个事务“泄露”到其他事务,这样可能会导致该用户在不注意的情况下购买两张同一航班的机票。 随着应用程序采用脱机行为的能力不断增强(例如,先在本地存储值,过段时间后才将其返回到服务器),此类信息“泄露”的可能性变得更为普遍。
另外,DOM 存储提供的磁盘空间要比 Cookie 大很多。 在 Internet Explorer 中,Cookie 只能存储 4 KB 的数据。 对于此字节总数,既可以是一个名称/值对的大小为 4 KB,也可以是最多 20 个名称/值对的总大小为 4 KB。 相比之下,DOM 存储可为每个存储区域提供大约 10 MB 的大小。
从功能上讲,客户端存储区域与 Cookie 截然不同。 DOM 存储既不会像 Cookie 一样在每次请求时将值传递给服务器,也不会出现存储在本地区域中的数据过期的情况。 另外,与 Cookie 不同的是,通过使用各浏览器供应商日益支持的标准接口,可以很容易地访问数据的各个部分。
DOM 存储脚本编写对象
- window.sessionStorage
- window.localStorage
- Storage 对象
window.sessionStorage
会话存储是针对用户执行单个事务的方案而设计的。 window 对象的 sessionStorage 属性可维护在单一选项卡的生存期间加载的所有页面的键/值对(针对顶层浏览上下文的持续时间)。 例如,某个页面可能会有一个复选框,用户可以选中此复选框以指示其想购买保险。
<label> <input type="checkbox" onchange="sessionStorage.insurance = checked"> I want insurance on this trip. </label>
下一个页面可能会利用脚本检查用户是否已选中该复选框。
if (sessionStorage.insurance) { ... }
Storage 对象支持 expando 属性(在前一个示例中为“insurance”)。 如果该属性名称不存在,则会自动创建一个键/值对来保存该名称。 注意,键/值对始终以字符串的形式存储。 必须将不同的数据类型(例如,数字、布尔值和结构化数据)转换为字符串,然后才能持久保留在存储区域中。
在将某个值保存到 sessionStorage 中之后,相同上下文的其他页面中运行的脚本可以检索该值。 当加载另一个文档时,将针对同源 URL 从内存中初始化 sessionStorage。 (有关详细信息,请参见安全和隐私部分。)
注意 即使 HTML 5(工作草案)(可能为英文网页) 允许,Internet Explorer 8 也不会在浏览器故障得到恢复后继续使用 sessionStorage。
window.localStorage
本地存储机制跨多个窗口,且持续范围可超过当前会话。 localStorage 属性可为域提供持久存储区域。 出于性能方面的考虑,该属性允许 Web 应用程序在客户端上存储接近 10 MB 的用户数据,例如,整个文档或用户的邮箱。
例如,网站可以使用以下脚本,显示用户已访问某个页面的次数的计数。
<p> You have viewed this page <span id="count">an untold number of</span> time(s). </p> <script> var storage = window.localStorage; if (!storage.pageLoadCount) storage.pageLoadCount = 0; storage.pageLoadCount = parseInt(storage.pageLoadCount, 10) + 1; document.getElementById('count').innerHTML = storage.pageLoadCount; </script>
注意 在递增 pageLoadCount 之前,必须先使用 parseInt 方法 (JScript 5.6)(可能为英文网页) 将其转换为数值。
每个域和子域都具有自己单独的本地存储区域。 域可以访问子域的存储区域,而子域也可以访问父域的存储区域。 例如, localStorage['example.com']
可由 example.com
及其任何子域访问。 子域 localStorage['www.example.com']
可由 example.com
访问,但不能由其他子域访问,如 mail.example.com
。
Storage 对象
会话和本地存储对象均支持下列属性和方法。
从 DOM 存储区域中移除所有键/值对。
返回对对象的构造函数的引用。
检索与 DOM 存储键关联的当前值。
检索集合中指定索引处的键。
检索键/值列表的长度。
检索可用于存储对象的剩余内存空间(以字节为单位)。
从 DOM 存储集合中删除键/值对。
设置键/值对。
DOM 存储事件
当更新存储区域中的数据时,Internet Explorer 将触发相应事件,以便在浏览器或选项卡的多个实例之间能够保持信息同步。
支持以下事件。
- onstorage
- onstoragecommit
onstorage
当存储区域发生更改时,document 中将触发 onstorage 事件。 所有共享相同会话上下文的文档,以及当前显示来自相同域或子域(即,本地存储将要提交到的域或子域)的页面的文档,都会接收到该事件。
如果目标文档对象当前未处于活动状态,则 Internet Explorer 不会触发任何事件。
onstoragecommit
Internet Explorer 使用 XML 文件来存储本地存储数据。 将本地存储数据写入到磁盘上时,将触发 onstoragecommit 事件。
安全和隐私
存储在 Cookie 中的数据可限定为某个域内的特定路径,与之相比,存储在本地存储区的数据更为公开。 即使选取难以猜到的密钥,也无法保证隐私,因为 Storage 对象提供了用于枚举相关数据的方法。
以下是一些注意事项:
- 顶层浏览上下文和源
- 源确定存储限制
- 清除存储区域
顶层浏览上下文和源
对会话存储区域的访问受顶层浏览上下文的限制。 在 Internet Explorer 中,将会为每个选项卡新建一个浏览上下文。 在一个顶层浏览上下文中运行的脚本无权访问在另一个浏览上下文中创建的存储区。 站点可以将数据添加到会话存储区中,然后将可从在同一窗口中打开的来自该源的任何页面访问这些数据。
源由协议、主机名(或 IP 地址)和域的 URL 的端口号确定。 仅当脚本源与存储区域的源相匹配时,才允许通过脚本访问存储数据。
源确定存储限制
磁盘配额限制将施加于设置相应值的页面所在的域,而不是施加于在其中设置相应值的域。 这可防止恶意脚本用尽相关域的存储配额。 同时还可阻止此类脚本使用随机子域来存储无限数量的数据。
存储大小是按照所有的键名称和值的总长度来计算的,一个存储区域最多可以包含 10,000,000 个字节。 remainingSpace 属性用于确定可用的存储空间。
清除存储区域
在关闭引用会话状态数据的最后一个窗口之后,将会立即释放相应的会话状态。 不过,用户可以通过在 Internet Explorer 中选择“工具”菜单上的“删除浏览的历史记录”,然后选中“Cookie”复选框并单击“确定”,随时清除存储区域。 这将清除未在“收藏夹”文件夹中的所有域的会话和本地存储区域,并重置注册表中的存储配额。 清除“保留收藏夹网站数据”复选框将会删除所有存储区域,而不考虑源。
若要从存储列表中删除键/值对,请使用 removeItem 遍历相应的集合,或者使用 clear 一次性删除所有项。 请记住,对本地存储区域的更改将以异步方式保存到磁盘中。