摘要:HTML5是一个新的HTML标准,它拥有大量新的功能和布局技术。它完全支持多媒体、CSS3以及使用画布和可缩放矢量图形(Scalable Vector Graphics, SVG)的绘图功能。HTML5供了新的语义元素,还提供了恰当的使用应用程序缓存器、JavaScript worker、新版本的XMLHttpRequest 一种名为Web存储的工具创建HTML Web应用程序的方式。
本文将探讨Web存储的强大功能,以及它成为一种优于cookies的存储方法的原因。通过本文您将了解基本概念、浏览器支持和HTML5 Web存储对象。
概述
Cookies从JavaScript出现之初就一直存在,所以在Web上存储数据并不是个新概念。不过Web存储是数据存储的一种更为强大的版本,可提供更多的安全性、速度和易用性。在Web存储中还可以存储数量巨大的数据。具体的数量则取决于Web浏览器,但通常都在5MB到10MB之间,这对于一个HTML应用程序而言已经足够大。另一个好处是此数据并不会在每次出现服务器请求时都被加载。惟一的限制是不能在浏览器之间分享Web存储, 如果您在Safari中存储了数据,那么该数据在Mozilla Firefox中是无法访问的。
内置到HTML5中的Web存储对象有两种类型:
- sessionStorage 对象负责存储一个会话的数据。如果用户关闭了页面或浏览器,则会销毁数据。
- The localStorage 对象负责存储没有到期的数据。当Web页面或浏览器关闭时,仍会保持数据的存储,当然这还取决于为此用户的浏览器设置的存储量。
常用的缩写语
- API:应用程序编程接口 (Application Programming Interface)
- CSS:级联样式表 (Cascading Style Sheet)
- HTML:超文本标记语言 (HyperText Markup Language)
- JSON:JavaScript Serialized Object Notation
这两种存储对象具有相同的方法和属性。为了获得一致性,本文在所有的示例中使用的都是localStorage对象。
在本文中,我们将了解Web存储的强大功能,以及它成为优于cookies的一种存储方式的原因。本文还将探索基本的Web存储概念、HTML5 Web存储方法和浏览器支持。
您可以下载 本文示例中使用的源代码。
浏览器支持
所有最新的浏览器版本均支持Web存储特性,这些浏览器包括Firefox、Google Chrome、Safari、Opera和Microsoft® Windows® Internet Explorer® 8+。不幸地是,Internet Explorer 7和更早版本不支持Web存储。表 1显示了支持 HTML5 Web存储的每个桌面浏览器版本。
表 1. HTML5 Web存储的桌面浏览器支持
除了Opera Mini之外,其他移动浏览器也提供了对HTML5 Web存储的支持。表 2 显示了支持HTML5 Web存储的每个移动浏览器版本。
表 2. HTML5 Web存储的移动浏览器支持
HTML5 Web存储的浏览器支持十分令人瞩目。但是,较老的浏览器要求在使用之前检查Web存储支持的浏览器。为了了解Web存储支持而对浏览器进行检查非常简单。可以使用一个简单的条件语句来查看HTML5存储对象是否已经定义。如果已经定义,就可以放心进行Web存储脚本编写。如果未定义,而数据存储又是必需的,则需要采用一种备选方法,比如JavaScript cookie。清单 1的例子显示了一种简单的为Storage对象进行浏览器检查的方式。
清单 1.Web存储支持的浏览器检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<ol class="dp-xml"> <li class="alt"> <span><span>if(typeof(Storage)!== "undefined") { </span></span> </li> <li> <span> // Web storage is supported </span> </li> <li class="alt"> <span>} </span> </li> <li> <span>else { </span> </li> <li class="alt"> <span> // Web storage is NOT supported </span> </li> <li> <span>} </span> </li> </ol> |
如果浏览器不支持Web存储,那么您可以使用JavaScript cookie或一个现有的库(比如 AmplifyJS)来创建一个定制的Web存储对象。AmplifyJS是一组组件,旨在通过一个简单的API解决常见Web应用程序问题,包括某些浏览器中的Web存储支持。AmplifyJS用amplify.store包装程序来处理持久的客户端存储,它支持Internet Explorer 5+、Firefox 2+、Safari 4+、Chrome、Opera 10.5+、iOS 2+ 和 Android 2+。这个库还支持一个持久的API来处理跨浏览器存储;您无需基于具体的浏览器编写不同的代码。如果浏览器支持HTML5 Web存储,那么AmplifyJS就会使用最新的存储技术。如果浏览器不支持HTML5 Web存储,那么AmplifyJS就会降级,以支持没有该功能的存储。请参阅参考资料,更多地了解AmplifyJS以及用于其存储包装程序的API。
入门
有几种简单易用的方法可提供HTML5 Web存储功能。这些方法支持设置一个键/值对,提供了两个基于键来检索某个值的选项,同时清除所有的键/值对,并删除了某个特定的键/值对。表3显示了可用的HTML5 Web存储方法。
表 3.HTML5 Web存储方法
在创建并将键/值对添加到此Web存储对象时,可以使用任何类型作为键/值对中的值(字符串、数值、数组、对象等)。要存储一个数组或对象,则必须使用JSON对象通过JSON.stringify 方法将数据转换为一个字符串。在检索此数据时,可以使用JSON.parse 进行检索,它会返回原始状态的对象或数据。还有两种向Web存储对象添加键/值对的不同方式。第一种方式是使用setItem方法,如清单 2所示。
清单 2.使用setItem方法向Web存储对象添加键/值对
1 2 3 4 5 6 7 |
<ol class="dp-xml"> <li class="alt"> <span><span>localStorage.setItem(\'myKey\', \'myValue\'); </span></span> </li> </ol> |
向Web存储对象添加键/值对的第二种方法是使用带dot参数的Web存储对象来直接设置此键的值,如清单 3所示。
清单 3.直接向Web存储对象添加键/值对
1 2 3 4 5 6 7 |
<ol class="dp-xml"> <li class="alt"> <span><span class="attribute">localStorage.myKey</span><span> = </span><span class="attribute-value">\'myValue\'</span><span>; </span></span> </li> </ol> |
检索所存储的值同样十分简单,也有两种方式。第一种方式是使用getItem方法,它接受键作为参数并返回相应的值(如果存在)。清单 4显示了一个示例。
清单 4.使用getItem从Web存储对象中检索键/值对
1 2 3 4 5 6 7 |
<ol class="dp-xml"> <li class="alt"> <span><span>localStorage.getItem(\'myKey\'); </span></span> </li> </ol> |
从Web存储对象中检索键/值对的第二个方法是使用dot参数直接访问它,如清单5所示。该示例返回了在之前的例子中设置的 \'myValue\'字符串值。
清单 5.直接从Web存储对象中检索键/值对
1 2 3 4 5 6 7 |
<ol class="dp-xml"> <li class="alt"> <span><span>localStorage.myKey; </span></span> </li> </ol> |
有两种方法可以删除所存储的数据。可以同时删除所有项,也可以一次删除个别项。要同时从Web存储对象中删除所有项,可以使用clear方法,如清单6所示。
清单 6.从Web存储对象中删除所有键/值对
1 2 3 4 5 6 7 |
<ol class="dp-xml"> <li class="alt"> <span><span>localStorage.clear(); </span></span> </li> </ol> |
要从Web存储对象中删除单个键/值对,需要使用removeItem方法。清单7显示了removeItem方法的一个示例,它接受一个键作为参数,并确定哪个键/值对要从此存储对象删除。
清单 7.从Web存储对象中删除单个键/值对
1 2 3 4 5 6 7 |
<ol class="dp-xml"> <li class="alt"> <span><span>localStorage.removeItem(\'myKey\'); </span></span> </li> </ol> |
清单 8显示了一个如何使用JSON对象通过JSON.stringify方法将一个数组存储为字符串的示例。可以采用相同的方法处理对象。
清单 8.在HTML5 Web存储中将一个数组存储为字符串
1 2 3 4 5 6 7 8 9 10 11 |
<ol class="dp-xml"> <li class="alt"> <span><span>var </span><span class="attribute">myArray</span><span> = </span><span class="attribute-value">new</span><span> Array(\'First Name\', \'Last Name\', \'Email Address\'); </span></span> </li> <li> <span class="attribute">localStorage.formData</span><span> = </span><span class="attribute-value">JSON</span><span>.stringify(myArray); </span> </li> </ol> |
要从Web存储检索数组的字符串版本,并将它转换回一个可用的JavaScript数组,只需使用JSON.parse方法,如清单9所示。
清单 9.从HTML5 Web存储中检索数组的字符串版本并将它转换成一个可用的JavaScript数组
1 2 3 4 5 6 7 |
<ol class="dp-xml"> <li class="alt"> <span><span>var </span><span class="attribute">myArray</span><span> = </span><span class="attribute-value">JSON</span><span>.parse(localStorage.formData); </span></span> </li> </ol> |
Internet Explorer 8+、Opera 10.5+、Firefox 3.5+、Safari 4+ 和 Chrome 均包括了一个本地的JSON对象,可以使用该对象来支持之前例子中的那些代码。如果您使用的是版本较早的浏览器,那么可以下载json2.js 文件(请参阅 参考资料)。
到目前为止,Web存储看起来很容易使用。但是,在开始使用之前,您应该意识到在共享的机器上会存在安全性问题。Web存储并不比cookies安全。所以不要在客户端存储敏感信息,比如密码或信用卡信息。
工作中的Web存储
介绍完基础知识后,现在是时候将HTML5 Web存储付诸于使用了。假设在您的网站上,您想要为一个Web表单提供离线支持。如果用户提交了表单,并且在网站恢复在线时让此表单与服务器同步,那岂不是很不错。HTML5可以实现此目标。
创建一个简单的Web表单,其中包含姓名、电子邮件地址和提交按钮,如清单10所示。
清单 10.使用HTML5 Web存储来存储数据的一个简单Web表单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
<ol class="dp-xml"> <li class="alt"> <span><span class="tag"><</span><span class="tag-name">html</span><span class="tag">></span><span> </span></span> </li> <li> <span class="tag"><</span><span class="tag-name">head</span><span class="tag">></span><span> </span> </li> <li class="alt"> <span class="tag"><</span><span class="tag-name">meta</span><span> </span><span class="attribute">http-equiv</span><span>=</span><span class="attribute-value">"Content-Type"</span><span> </span><span class="attribute">content</span><span>=</span><span class="attribute-value">"text/html; charset=UTF-8"</span><span class="tag">></span><span> </span> </li> <li> <span class="tag"><</span><span class="tag-name">title</span><span class="tag">></span><span>HTML5 Web Storage</span><span class="tag"></</span><span class="tag-name">title</span><span class="tag">></span><span> </span> </li> <li class="alt"> <span class="tag"><</span><span class="tag-name">style</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/css"</span><span class="tag">></span><span> </span> </li> <li> <span>label, </span> </li> <li class="alt"> <span>input { </span> </li> <li> <span> display: block; </span> </li> <li class="alt"> <span>} </span> </li> <li> <span>input { </span> </li> <li class="alt"> <span> margin-bottom: 10px; </span> </li> <li> <span>} </span> </li> <li class="alt"> <span class="tag"></</span><span class="tag-name">style</span><span class="tag">></span><span> </span> </li> <li> <span class="tag"></</span><span class="tag-name">head</span><span class="tag">></span><span> </span> </li> <li class="alt"> <span> </span> </li> <li> <span class="tag"><</span><span class="tag-name">body</span><span class="tag">></span><span> </span> </li> <li class="alt"> <span> </span> </li> <li> <span class="tag"><</span><span class="tag-name">form</span><span> </span><span class="attribute">action</span><span>=</span><span class="attribute-value">"post.php"</span><span> </span><span class="attribute">method</span><span>=</span><span class="attribute-value">"post"</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"web-storage-form"</span><span class="tag">></span><span> </span> </li> <li class="alt"> <span> </span><span class="tag"><</span><span class="tag-name">label</span><span> </span><span class="attribute">for</span><span>=</span><span class="attribute-value">"first-name"</span><span class="tag">></span><span>First name:</span><span class="tag"></</span><span class="tag-name">label</span><span class="tag">></span><span> </span> </li> <li> <span> </span><span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text"</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"first-name"</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"first-name"</span><span class="tag">></span><span> </span> </li> <li class="alt"> <span> </span> </li> <li> <span> </span><span class="tag"><</span><span class="tag-name">label</span><span> </span><span class="attribute">for</span><span>=</span><span class="attribute-value">"last-name"</span><span class="tag">></span><span>Last name:</span><span class="tag"></</span><span class="tag-name">label</span><span class="tag">></span><span> </span> </li> <li class="alt"> <span> </span><span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text"</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"last-name"</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"last-name"</span><span class="tag">></span><span> </span> </li> <li> <span> </span> </li> <li class="alt"> <span> </span><span class="tag"><</span><span class="tag-name">label</span><span> </span><span class="attribute">for</span><span>=</span><span class="attribute-value">"email-address"</span><span class="tag">></span><span>Email Address:</span><span class="tag"></</span><span class="tag-name">label</span><span class="tag">></span><span> </span> </li> <li> <span> </span><span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text"</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"email-address"</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"email-address"</span><span class="tag">></span><span> </span> </li> <li class="alt"> <span> </span> </li> <li> <span> </span><span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"submit"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"Submit"</span><span class="tag">></span><span> </span> </li> <li class="alt"> <span class="tag"></</span><span class="tag-name">form</span><span class="tag">></span><span> </span> </li> <li> <span> </span> </li> <li class="alt"> <span class="tag"></</span><span class="tag-name">body</span><span class="tag">></span><span> </span> </li> <li> <span class="tag"></</span><span class="tag-name">html</span><span class="tag">></span><span> </span> </li> </ol> |
此表单包含了一个ID,可使用JavaScript检索表单post和值。此外,它还提供了CSS,以创建具有表单元素的基本布局。标签和输入上的display:block 将每个元素置于一个新行。margin-bottom属性在条目之间创建空间,让页面看起来不会太乱。
当用户提交表单时,代码首先会检索web-storage-form ID并使用jQuery捕获默认张贴,以阻止此张贴操作的发生。当张贴表单时,就可以收集表单值以及此表单动作的URL,以便将它们存储在变量中。在作为Asynchronous JavaScript + XML (Ajax) post发送表单值,或将它们存储于Web存储中时,您还需要序列化这些Web表单值。在提交表单之前,应该使用navigator.onLine属性查看用户当前是否在线。
如果用户在线,则使用jQuery.post函数,这是一个简略的Ajax函数,用于发送数据并从服务器接收数据。这个函数接受四个参数:数据被发送到的url、正在发送的data(序列化后的表单值)、请求成功便会触发的callback函数以及dataType。在本例中,并未包括dataType,所以会使用默认参数。
如果用户不在线,那么就可以让Web存储一展身手了。首先也是很重要的一点是,使用 清单1中创建的条件语句来查看浏览器是否支持Web存储。如果浏览器不支持 Web 存储,则使用一个定制键将表单值直接存储到localStorage 对象中。本例使用了formValues定制键。localStorage值的已经保存,现在可以检查当用户恢复在线时这些值是否存在,做法是通过添加一个if语句来检查localStorage.formValues是否有一个值。如果有一个值,则表明这个表单之前已经提交到 localStorage,并可以使用先前设置好的jQuery.post方法安全地向服务器发送数据。在提交值之后,应该从Web存储中将它们删除,以防止意外地重复提交它们。清单11显示了从使用Ajax的表单张贴到localStorage期间所需代码。
清单 11. 离线时将表单数据存储于localStorage,在线时将其提交到服务器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
<ol class="dp-xml"> <li class="alt"> <span><span class="tag"><</span><span class="tag-name">script</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/javascript"</span><span> </span></span> </li> <li> <span class="attribute">src</span><span>=</span><span class="attribute-value">"https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"</span><span class="tag">></span><span> </span> </li> <li class="alt"> <span class="tag"></</span><span class="tag-name">script</span><span class="tag">></span><span> </span> </li> <li> <span class="tag"><</span><span class="tag-name">script</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/javascript"</span><span class="tag">></span><span> </span> </li> <li class="alt"> <span>$(document).ready(function() { </span> </li> <li> <span> // Check for web storage values from a previous offline session </span> </li> <li class="alt"> <span> if(localStorage.formValues) { </span> </li> <li> <span> console.log("localStorage.formValues: "+ localStorage.formValues); </span> </li> <li class="alt"> <span> postForm($("#web-storage-form").attr(\'action\'), localStorage.formValues); </span> </li> <li> <span> localStorage.removeItem("formValues"); </span> </li> <li class="alt"> <span> } </span> </li> <li> <span> </span> </li> <li class="alt"> <span> $("#web-storage-form").submit(function(event) { </span> </li> <li> <span> // Prevent the form from posting </span> </li> <li class="alt"> <span> event.preventDefault(); </span> </li> <li> <span> </span> </li> <li class="alt"> <span> // Gather values </span> </li> <li> <span> var </span><span class="attribute">formValues</span><span> = $(this).serialize(); </span> </li> <li class="alt"> <span> var </span><span class="attribute">url</span><span> = $(this).attr(\'action\'); </span> </li> <li> <span> postForm(url, formValues); </span> </li> <li class="alt"> <span> }); </span> </li> <li> <span> }); </span> </li> <li class="alt"> <span> </span> </li> <li> <span>function postForm(url, formValues) { </span> </li> <li class="alt"> <span> // Post to server or post to web storage </span> </li> <li> <span> if(navigator.onLine) { </span> </li> <li class="alt"> <span> console.log("Online"); </span> </li> <li> <span> $.post(url, formValues, function(data) { </span> </li> <li class="alt"> <span> console.log("Success: "+ data); </span> </li> <li> <span> }); </span> </li> <li class="alt"> <span> } </span> </li> <li> <span> else { </span> </li> <li class="alt"> <span> console.log("Offline"); </span> </li> <li> <span> if(typeof(Storage) !== "undefined") { </span> </li> <li class="alt"> <span> console.log("Storage supported"); </span> </li> <li> <span> </span><span class="attribute">localStorage.formValues</span><span> = formValues; </span> </li> <li class="alt"> <span> } </span> </li> <li> <span> } </span> </li> <li class="alt"> <span>} </span> </li> <li> <span class="tag"></</span><span class="tag-name">script</span><span class="tag">></span><span> </span> </li> </ol> |
为了创建一个完整的例子,使用post.php 文件充当表单张贴的结尾,用以接收和响应表单请求。这个文件只简单接收表单张贴并通过打印键/值对进行响应,如清单12所示。当jQuery.post收到响应后,就可以将来自响应的数据写入控制台了。
清单 12.可响应表单请求的PHP文件
1 2 3 4 5 6 7 |
<ol class="dp-xml"> <li class="alt"> <span><span class="tag"><?</span><span class="tag-name">php</span><span> print_r($_POST); </span><span class="tag">?></span><span> </span></span> </li> </ol> |
当然,您还可以让这个例子更为健壮。比如,您可以在服务器端上提供数据库存储,并使用一个间隔来检查localStorage,以便随时监视用户的计算机是否恢复在线,从而提交表单数据。
结束语
HTML5提供了一组强大的新功能,并迅速获得了主要Web浏览器的最新版本的支持。Web存储是HTML5众多引人注目的特性中的一个。但是,务必巧妙使用它。对于cookie,用户可以关闭Web存储。始终都要有一个备案,以便支持那些不想使用此新功能的用户。
来自:IBM社区中文站