本质上,HTML5规范提供了3种不同的客户端存储机制。
● Web Storage:通常叫做HTML5本地存储,这是存储键/值对的一种客户端机制。它很简单,但却非常强大(请参阅http://w3.org/TR/webstorage/)。
● Web SQL Database:它可以访问类似于SQLite的数据库,这是传统的服务器端RDBMS的客户端解决方案(请参阅http://w3.org/TR/webdatabase/)。
● Indexed Database:W3C提出的草案规范,用于替代目前实现的Web SQL Database规范,其目的是提供一种“持有简单值与层级对象的记录数据库
localStorage与sessionStorage对象都实现了Storage接口,并且提供了如下方法:
● getItem
● setItem
● removeItem
● clear
这4个方法涵盖了Storage API的所有功能,虽然很简单,但却为我们提供了很多机会。真正的魔力在于你可以将任意对象存储到Storage中。之后,只需要通过键就可以获取到对应的值。
举个简单的例子,可以将字符串或其他简单的类型值保存到Storage中。先来查看如下代码:
localStorage.setItem("preferences-bgcolor", "#333333");
localStorage.setItem("preferences- textcolor", "#FFFFFF");
这会在localStorage中创建两个值,用于追踪应用首选项的背景与文本颜色。然而,可以通过将单一对象存储到localStorage中实现同样的效果,如下代码所示:
localStorage.setItem("preferences", {
bgcolor: "#333333",
textcolor: "#FFFFFF"
});
只需要通过调用getItem就可以获取到preferences对象:
var preferences =
localStorage.getItem("preferences");
接下来,可以从preferences对象中得到背景色与文本颜色的首选项。现在来试一下,只是弹出一个警告框来显示背景颜色:
alert(preferences.bgcolor);
喔,有些尴尬。根据你阅读本书时浏览器所使用的Web Storage API实现的不同,你会发现上述调用只会显示出图3-1所示的JavaScript警告消息。
这意味着什么呢?只能在localStorage与sessionStorage中存储简单值么?是这样的,但可以使用JSON(JavaScript Object Notation)序列化对象,然后再将其保存为字符串。这么做是值得的,因此本章的第一个练习就采取了这种做法。
说明:
如果之前没有遇到过这种情况,那么欢迎你进入早期技术使用者的世界中来—事情已经发生了变化。我们之前曾介绍过这一点,该示例证明了浏览器构建者认为HTML5的部分规范对于实现来说已经足够稳定了,但实际上还是会有一些问题。这很有趣,这类示例在本书中还会继续出现。
如果你遇到某些程序的运行结果与预期不同,或是本书中的某些内容与当前的HTML5规范不一致,那么请在线提交反馈,地址是www.apress.com。
3.1.1 使用JSON将对象保存到Web Storage中
现在来看看如何使用JSON将JavaScript对象保存到Web Storage中。JSON提供了一种优雅且高效的方法将JavaScript对象数据保存为普通的文本字符串。转换为字符串格式后,数据就可以发送给外部服务或是作为示例使用。但在将对象保存为JSON格式前,需要使用Douglas Crockford编写的json2.js库将对象序列化为JSON字符串以及将JSON字符串反序列化为对象。该库的地址如下所示:http://json.org/json2.js。
可以将该文件下载到顶层的js目录中以供后续的其他练习使用。
说明:
Douglas Crockford在json2.js文件的第一行使用了一个警告,不建议开发者通过直接链接到其站点的方式使用该库。你在运行练习中的代码示例前需要移除该警告。但如果忘记了也没事,只不过在每次运行使用了JSON的练习时需要单击一下这个恼人的警告框而已。我相信等到你阅读完本书时一定会移除该行警告。
现在来创建一个简单的页面,用于搭建测试的运行环境:
<html>
<head>
<title>Web Storage Tester</title>
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
<link rel="stylesheet" media="screen" href="../../css/snippets.css" />
<script type="text/javascript" src="../../js/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="../../js/json2.js"></script>
<script type="text/javascript" src="../../js/prowebapps.js"></script>
<script type="text/javascript" src="webstorage-test.js"></script>
</head>
<body>
<h1 class="fancy">Web Storage JSON Wrapper</h1>
<ul id="items">
<li class="header">Items in Storage (tap to remove)</li>
</ul>
<ul id="newitem">
<li class="header">New Item</li>
<li class="bordered"><input type="text" id="newtitle" placeholder="Title"/></li>
</ul>
<ul id="actions">
<li><button id="add">Add</button></li>
<li><button id="clear">Clear</button></li>
</ul>
</body>
<html>
上述代码中有4点值得注意。
● 包含了通用的snippets样式表(css/snippets.css)。第1章曾说过,该样式表是可重用代码组件的一部分,我们将在全书中使用并扩展它。该样式表的完整源代码位于如下地址:http://sidelab.com/code/pawa/css/snippets.css。
● 包含了json2.js,这样我们就可以使用JSON序列化与解析了。
● 包含了prowebapps.js库。我们会添加一些便利的包装器以将对象保存到localStorage/sessionStorage,它通过JSON提供了自动的对象序列化/反序列化功能。
● 包含了webstorage-test.js,它包含了该练习所需的JavaScript代码。
现在继续编写代码。首先,我们将这些存储包装器函数添加到prowebapps.js库中。这是通过向已有的PROWEBAPPS模块中添加一个Storage子模块实现的:
var module = {
Storage: (function() {
function getStorageScope(scope) {
if (scope && (scope == "session")) {
return sessionStorage;
} // if
return localStorage;
} // getStorageTarget
return {
get: function(key, scope) {
// get the storage target
var value = getStorageScope(scope).getItem(key);
// if the value looks like serialized JSON, parse it
return (/^(\{|\[).*(\}|\])$/).test(value) ? JSON.parse(value) : value; },
set: function(key, value, scope) {
// if the value is an object, then stringify using JSON
var serializable = jQuery.isArray(value) || jQuery.isPlainObject(value);
var storeValue = serializable ? JSON.stringify(value) : value;
// save the value
getStorageScope(scope).setItem(key, storeValue);
},
remove: function(key, scope) {
getStorageScope(scope).removeItem(key);
}
};
})()
...
};
虽然我们并不打算详细解释上述代码,但感兴趣的读者会发现我们将HTML5 Storage接口中的getItem与setItem方法包装到了PROWEBAPPS.Storage模块的get与set静态方法中。我们使用一些jQuery辅助函数与正则表达式来确定是否需要使用JSON来存储/获取数据,如果需要,那就使用JSON来做。
比了解上述代码的运行机制(如果将这些代码进行分解,你就会发现它其实很简单)更为重要的是该如何使用这些代码。基本上,我们现在有3个函数可以实现更加复杂的值存储功能,我们可以使用它们与HTML5 Web Storage功能进行交互。
● PROWEBAPPS.Storage.get(key, scope)
§ key是一个用于标识条目的字符串值。
§ 如果你想存储到session storage而非local storage,那么可以将scope指定为“session”(以字符串形式)。
● PROWEBAPPS.Storage.set(key, value, scope)
§ 与get方法一样,key是用于标识条目的字符串值。
§ value是我们想要保存到Web Storage中的数据(可以是简单值、数组、对象等)。数组与对象使用JSON进行序列化,然后存储为字符串。
§ scope(可选)指定键值存储到session还是local storage中。如果不为该参数赋值,那么值就会被存储到local storage中。
● PROWEBAPPS.Storage.remove(key, scope)
§ key是一个字符串值,用于标识将从storage中移除的条目。
§ scope参数(如果提供)用于指定使用session还是local storage。如果不提供值,那么默认将会使用local storage。
介绍完这些功能后,现在来看看如何使用PROWEBAPPS.Storage函数存储简单的JavaScript对象与数组。我们通过创建webstorage-test.js文件做到这一点,它用于强化这个简单的存储测试应用:
$(document).ready(function() {
// read the data from local storage for the items
var items = PROWEBAPPS.Storage.get("listitems");
var loadTicks = new Date().getTime();
functiondisplayItems() {
loadTicks = new Date().getTime();
$("#items li[class!='header']").remove();
if (items) {
// create list items to display the current items
for (var ii = 0; ii <items.length; ii++) {
varitemAge = Math.floor((loadTicks - items[ii].created) / 1000);
$("#items").append("<li>" + items[ii].title + " (created " + itemAge +"s ago)</li>");
} // for
}
else {
$("#items").append("<li>No items</li>");
// initialize the items array
items = [];
} // if..else
} // displayItems
// button click handlers go here
displayItems();
});
上述代码非常简单,用于从localStorage中获取条目数组(listitems)并将其显示在屏幕上。使用之前编写的代码(没有定义add与clear功能),加载页面会生成HTML输出,如图3-2所示。
图3-2 Web Storage测试应用页面
由于现在的storage中并没有条目(PROWEBAPPS.Storage.get函数返回null),因此屏幕上显示出了“No items”。现在来实现add与clear按钮的单击处理程序以填充并保存数组:
$("#add").click(function() {
items.push({
title: $("#newtitle").val(),
created: new Date().getTime()
});
// save the items
PROWEBAPPS.Storage.set("listitems", items);
displayItems();
});
$("#clear").click(function() {
items = null;
PROWEBAPPS.Storage.remove("listitems");
displayItems();
});
同样,上述代码也非常简单。对于add处理程序来说,我们使用条目的标题与当前时间(以毫秒表示)向数组中添加新的对象、将条目保存到storage中,然后刷新显示。
clear处理程序更简单。我们将items变量的状态重置为null、从local storage中移除listitems,然后更新显示。
本文摘自:
android web 应用应用高级编程
ISBN 978-7-302-28050-7
原书名:
Pro Android Web Apps: Develop for Android Using HTML5, CSS3 & JavaScript
出版社:清华大学出版社
互动网链接: