现在来看看如何使用 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,然后更新显示。