第三部分 ActionScript篇
第 章
Web存储
([pic] 视频讲解:69分钟)
Web应用的发展,使得客户端存储的用途也越来越多,而实现客户端存储的方式则是多种多样。最简单且兼容性最佳的方案是Cookie,但是作为真正的客户端存储,Cookie存在很多缺陷。HTML5提出了更多解决方案:如果存储复杂的数据,可以使用Web Database,该方法可以像客户端程序一样使用SQL;如果需要存储简单的key/value(键值对)信息,可以使用Web Storage。本章将主要介绍Cookie、Web Storage和Web Database。
【学习重点】
( 了解Cookie技术
( 正确存取Cookie信息
( 使用Web Storage技术存取信息
( 使用Web SQL技术存取信息
19.1 Cookie概述
HTTP是一种无序协议,它不会记录或跟踪用户的访问信息。这意味着Web服务器无法直接分辨用户的身份,记忆用户的足迹。不管是老用户,还是新用户,对于Web服务器来说,都是新面孔。这种无序状态能够在一定程度上降低服务器运行的复杂性,提高响应速度,当然也存在很多问题。例如,刚登录完毕,再次回来时就需要重新登录;刚设置的页面环境,如果刷新页面,则还需要重新设置;重复的表单信息,却需要反复输入。
19.1.1 认识Cookie
1995年Netscape 2.0版本浏览器推出,Netscape 2.0开始支持Cookie技术。Cookie是存储在用户系统中的一个文本文件,该文本文件与某个Web服务器域中的某个目录相关联,当用户的浏览器向服务器请求该目录中某个页面时,客户端的Cookie信息就会随着HTTP请求一起发送到服务器端。这样就可以使用JavaScript在客户端设置和检索Cookie信息,同时服务器端也能够读取这些Cookie信息,从而实现跟踪和记录用户访问的目的。
Cookie特别适合完成类似如下的各种工作:
← 跟踪访问者的访问次数、最后访问时间和访问者进入站点的路径等。
← 记录在线广告点击次数,记录用户是否投票、是否登录、是否选购等信息。
← 可以减轻表单输入的繁琐,只要输入一次,在有效时间内用户就不用再重复输入。
← 可以统计用户资料,并根据这些信息设计个性化服务。
← 可以记录用户的页面设置信息,避免重复配置环境。
由于Web服务器可以通过Cookie观察用户的浏览习惯,从而将用户信息加以细化,以方便站点为不同用户定制信息,实现个性化的服务。因此,Cookie一直是浏览器和服务器开发中钟情的一项技术,也确实为广大互联网用户带来了很大的便利。
19.1.2 Cookie字符串
在JavaScript中,一个Cookie实际就是一个字符串属性。当对Cookie进行读操作时,可以得到一个字符串,这个字符串包含了应用到当前文档的所有Cookie的名称和值。通过设置Cookie的值可以创建、修改或删除一个Cookie。除了名/值对外,每个Cookie都包含4个可选的属性,分别用来定义Cookie的有效期、可见性和安全性。
← 所谓有效期,就是Cookie存在的时间,由expires属性设置。在默认情况下,Cookie是临时存在的,当会话结束后就被删除(即浏览器被关闭后或退出Web服务器的域)。如果希望Cookie存在的时间超过一个浏览会话期,可以使用expires属性指定一个终止日期,这样浏览器就会把Cookie保存到一个本地文件中,以方便下次访问时读取。一旦超过了终止日期,那个Cookie就会自动从Cookie文件中删除。
← 可见性包括Cookie的路径(path)和域(domain)。path属性设置Cookie的有效路径(或者说可以访问的目录),默认为当前文件所在的目录。domain属性可以设置Cookie关联的域,即设置可以访问Cookie的站点,默认为当前站点。
← 安全性是指Cookie信息在客户端与服务器端传递时是否采取安全策略,它主要通过secure属性来设置,secure是一个布尔值,可以设置Cookie信息的传输方式。注意,expires、path、domain和secure都是Cookie的属性,而不是JavaScript对象的属性。
一个Cookie字符串应该由下面几部分组成。
← name(名称):每一个Cookie都有一个名称(具有唯一性,即一个Cookie中不能够包含多个名称)。这个名称可以包含字母、数字和下划线。与JavaScript变量不同,Cookie的名称是不区分大小写的。例如,name和Name是相同的。为了安全起见,建议保持大小写习惯,因为有些服务器端软件区分大小写。
← value(值):具体的Cookie信息,为了防止值中包含特殊的字符,建议使用JavaScript方法对其进行编码,当然在读取时也不要忘记解码。Cookie名称和值的字节数不能超过4096个字符(即4KB)。
← domain(域):不同网站只能够访问自己域内的Cookie信息,网站之间不能够互访。不过,用户可以通过设置域以实现网站之间的相互访问。
← path(路径):不同的Cookie信息只能够在指定的目录下有效,其他目录文件是禁止访问的。此时,可以通过该属性来设置有效访问的路径。
← expires(失效日期):Cookie信息仅是暂时存在的,不过通过设置expires属性可以延长Cookie的生存期。
← secure(安全标识):布尔值,当为true时,表示以安全方式传递Cookie信息,否则根据常规方式传递Cookie信息。
19.2 存取Cookie
用户可以使用JavaScript脚本操纵Cookie。本节将讲解如何使用JavaScript操纵Cookie。
19.2.1 写入Cookie
JavaScript在Document对象中定义了Cookie属性,该属性能够接收Cookie字符串信息,并把这些信息写入到客户端Cookie文件信息列表中。
【示例】使用cookie存储信息。
var c = "name=zhu";
document.cookie = c; //写入Cookie信息
Cookie字符串是一组名/值对,名称和值之间以等号相连,名/值对之间使用分号进行分隔。值中不能够包含分号、逗号和空白符。如果值中包含特殊字符,可以使用escape()函数对其进行编码,当然在读取Cookie信息时也必须使用unscape()函数进行解码。
var d = new Date();
d = d.toString();
d = "date=" + escape(d); //设置Cookie字符串
document.cookie = d; //写入Cookie信息
19.2.2 设置Cookie有效期
在默认状态下,Cookie信息只能在当前的Web浏览会话期(当前Web浏览窗口)中有效并存在,一旦退出浏览器,这些Cookie信息就会被自动删除。如果希望Cookie信息在客户端能够长久存在,可以通过expires属性来实现。
expires表示“有效期”的意思。设置expires属性的方法是:把字符串expires=date附加到Cookie属性值后面即可,语法格式如下:
name = value; expires = date
date采用的日期规范必须是格林威治时间(GMT),即按如下格式设置:
Sun, 30 Apr 2017 00:00:00 UTC
不过调用Date对象的Date.toGMTString()方法可以把时间对象快速转换为GMT格式。
【示例】本示例将创建一个有效期为一个月的Cookie信息。如果在本地系统中打开Cookie文件夹,可以看到新建的Cookie文本文件,其中已经存储了刚写入的用户信息。
var d = new Date(); //实例化当前日期对象
d.setMonth(d.getMonth() + 1); //提取月份值并加1,然后重新设置当前日期对象的月份值
d = "date=" + escape(d) +
";expires=" + d.toGMTString(); //在Cookie字符串的末尾添加expires名/值对
document.cookie = d; //写入Cookie信息
19.2.3 设置Cookie的域和路径
Cookie信息是有域和路径限制的。在默认情况下,仅在当前页面路径内有效。例如,如果在下面的页面中写入了Cookie信息:
那么这些Cookie信息将只会与路径下,以及其子目录下的页面相关联,其他域或本域其他目录中的文件是无权访问的。这种限制主要是为了保护用户信息的隐私,避免恶意存取。
不过这种限制比较大,通常开发人员会希望Cookie信息能够在整个网站内共享,即与网站内所有页面建立关联。这时就可以使用Cookie的path和domain属性。
path属性包含了与Cookie信息相关联的目录(即有效路径),而domain属性定义了Cookie信息的有效作用域。这些属性信息可以附加在Cookie字符串的末尾:
name=value; expires=date; domain= domain; path=path;
path属性设置了可以读取一个Cookie的最顶层目录,将Cookie的路径设置为网页最顶层的目录,就可以让该目录下所有网页都能访问这个Cookie。例如,如果设置path=/,则Cookie信息将会与服务器根目录及其子目录相关联,即在整个网站中共享。如果只想让bbs目录下的网页可以使用该Cookie,则加入path=/bbs即可。
对于一些网站来说,可能它还会包含很多小的域名(即子域名)。例如,对于百度来说,它就包含:
……
在默认情况下,Cookie信息只能够在本域文件中访问,这是Cookie的一种安全特性。不过,可以通过设置Cookie的domain属性来修改域的范围。例如,在文件中设置一个Cookie信息,则通过设置domain= tieba.属性,就可以在路径下访问该Cookie信息。
如果希望在所有子域中访问Cookie信息,则可以在Cookie中加入类似domain=的属性设置,这样该Cookie信息就与的所有子域下的所有页面相关联,包括www、news、tieba、zhidao、mp3等子域区域。
19.2.4 设置Cookie安全传输
Cookie支持secure属性,该属性定义了Cookie信息的安全性,它可以指定Cookie信息通过网络如何在客户端与Web服务器端之间进行传递。
secure属性取值包括secure或者空字符串。在默认情况下,secure属性值为空,也就是说Cookie信息使用不安全的HTTP连接传递数据。如果一个Cookie设置了secure,那么Cookie信息在客户端与Web服务器之间进行传递时,就通过HTTPS或者其他安全协议传递数据。
19.2.5 案例:完善写入Cookie方法
比较完善的Cookie信息字符串应该包括下面几个部分:
← Cookie信息字符串,包含一个名/值对,默认为空。
← Cookie有效期,包含一个GMT格式的字符串,默认为当前会话期,即如果没有设置,则当关闭浏览器时,cookie信息就因过期而被清除。
← Cookie有效路径,默认为Cookie所在页面目录及其子目录。
← Cookie有效域,默认为设置Cookie的页面所在的域。
← Cookie安全性,默认为不采用安全加密措施进行传递。
【示例】本示例把写入Cookie信息的实现代码进行封装。
//写入Cookie信息
//参数:name表示Cookie名称,value表示Cookie值,expires表示有效天数,path表示有效路径,domain表示域,secure表示安全性设置。其中name、value、path和domain参数为字符串类型,传递时需要加上引号,而参数expires为数值,secure表示布尔值,表示是否加密传输Cookie信息
//返回值:无
function setCookie( name, value, expires, path, domain, secure ){
var today = new Date(); //获取当前时间对象
today.setTime( today.getTime() ); //设置现在时间
if ( expires ){ //如果有效期参数存在,则转换为毫秒数
expires = expires * 1000 * 60 * 60 * 24;
}
var expires_date = new Date( today.getTime() + (expires) ); //新建有效期时间对象
document.cookie = name + "=" + escape( value ) +
//写入Cookie信息
(( expires ) ? ";expires=" + expires_date.toGMTString() : "") +
//指定有效期
(( path ) ? ";path=" + path : "" ) + //指定有效路径
(( domain ) ? ";domain=" + domain : "" ) + //指定有效域
(( secure ) ? ";secure" : "" ); //指定是否加密传输
}
19.2.6 读取Cookie信息
所有Cookie信息都存储在document.cookie属性中,该属性返回值是一个字符串,但是这个字符串的结构比较特殊,实际上它就是一个数据列表,通过分号和等号进行标记信息列表。
为了获取已写入的Cookie信息,用户需要先读取document.cookie属性值,该属性值是一个由零个或多个名/值对的子字符串组成的列表,每对之间通过分号进行分隔。
【示例1】可以采用下面的方法把Cookie字符串转换为对象类型。
//把Cookie字符串转换为对象类型
//参数:无
//返回值:对象,存储Cookie信息,其中名称作为对象的属性而存在,而值作为属性值而存在
function getCookie(){
var a = document.cookie.split(";"); //把Cookie字符串劈开为数组
var o = {}; //临时对象直接量
for(var i=0;i)/ig, "");
//编码特殊字符
//name = name.replace(/&/,"&");
//name = name.replace(//,">");
values.push(project);
values.push(hours);
values.push(date);
if (project == "" || project == "Project Name" || hours == "" || hours == "Hours" || date == "" || date == "Date") {
$("#emptyFields-message").dialog({
resizable: false,
height:140,
modal: true,
show: 'fold',
buttons: {
Ok: function() {
$(this).dialog('close');
}
}
});
} else {
try {
localStorage.setItem(itemId, values.join(';'));
} catch (e) {
if (e == QUOTA_EXCEEDED_ERR) {
alert('Quota exceeded!');
}
}
getAllItems();
}
});
$("#clearLog").click(function() {
$("#clearLog-message").dialog({
resizable: false,
height:140,
modal: true,
show: 'fold',
buttons: {
'Delete all items': function() {
localStorage.clear();
getAllItems();
$(this).dialog('close');
},
Cancel: function() {
$(this).dialog('close');
}
}
});
});
$("#aboutButton").click(function() {
$("#about").slideDown("slow");
});
$("#closeButton").click(function() {
$("#about").slideUp("slow");
});
}
});
19.6 Web SQL数据库
HTML5大大丰富了本地可存储的内容,添加了很多功能将原本必须要保存在服务器上的数据转为保存在本地,从而大大提高了Web应用程序的性能,减轻了服务器端的负担,使Web时代重新回到了客户端为重、服务器端为轻的时代。在这其中,一项非常重要的功能就是数据库的本地存储功能。在HTML5中内置了一个可以通过SQL语言来访问的数据库。在HTML4中,数据库只能放在服务器端,只能通过服务器来访问数据库,但是在HTML5中,可以像访问本地文件那样轻松地对内置数据库进行直接访问。
19.6.1 Web SQL数据库概述
以键/值对的形式存储数据的Storage API在数据持久化方面已经很强大了,但是HTML5应用同样可以访问索引数据库。数据库API的具体细节仍在完善中,并有多个方案。Web SQL Database是其中之一,并已经在Safari、Chrome和Opera中实现了,如表19-5所示显示了浏览器对于Web SQL Database的支持情况。
表19-5 浏览器支持概述
|浏 览 器 |说 明 |浏 览 器 |说 明 |
|IE |不支持 |Chrome |3.0及以上的版本支持 |
|Firefox |不支持 |Safari |3.2及以上的版本支持 |
|Opera |10.5及以上的版本支持 | | |
Web SQL Database允许应用程序通过一个异步JavaScript接口访问SQLLite数据库。虽然它既不是常见Web平台的一部分,也不是HTML5规范最终推荐的数据库API,但当针对如Safari移动版这样的特定平台时,SQL API很有用。在任何情况下,SQL API在浏览器中的数据库处理能力都是无可比拟的。与其他Storage API一样,浏览器能够限制同源页面可用Storage的大小,并且当用户数据被清除时,Storage中的数据也会被清除。
Web SQL数据库API实际上不是HTML5规范的组成部分,而是单独的规范。它通过一套API来操纵客户端的数据库。虽热Web SQL Database已经在Safari、Chrome和Opera中实砚,但是IE、Firefox中并没有实砚它,而且WHATWG也停止对Web SQL Database的开发。由于标准认定直接执行SQL语句不可取,Web SQL Database已被极新的规范—索引数据库(Indexed Database,原为WebSimpleDB)所取代。索引数据库更简便,而且不依赖于特定的SQL数据库版本。目前浏览器正在逐步实现对索引数据库的支持。
19.6.2 使用Web SQL数据库
SQL数据库已经得到了广泛的利用,所以HTML5也采用了这种数据库作为本地数据库。因此,如果先掌握了SQLLite数据库的基本知识,接着再学如何使用HTML5的数据库就不困难了。
HTML5数据库API是以一个独立规范的形式出现,它包含3个核心方法。
← openDatabase:使用现有数据库或创建新数据库的方式创建数据库对象。
← transaction:允许根据情况控制事务提交或回滚。
← executeSql:用于执行真实的SQL查询。
使用JavaScript脚本编写SQLLite数据库有两个必要的步骤。
← 创建访问数据库的对象。
← 使用事务处理。
1.创建或打开数据库
首先,必须要使用openDatabase()方法来创建一个访问数据库的对象。具体用法如下:
Database openDatabase(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in optional DatabaseCallback creationCallback)
openDatabase()方法可以打开已经存在的数据库,如果不存在则创建。openDatabase()方法中5个参数分别表示:数据库名、版本号、描述、数据库大小、创建回调。创建回调没有时也可以创建数据库。
【示例1】创建了一个数据库对象db,名称是Todo,版本编号为0.1。db还带有描述信息和大概的大小值。浏览器可使用这个描述与用户进行交流,说明数据库是用来做什么的。利用代码中提供的大小值,浏览器可以为内容留出足够的存储。如果需要,这个大小是可以改变的,所以没有必要预先假设允许用户使用多少空间。
db = openDatabase("ToDo", "0.1", "A list of to do items.", 200000);
为了检测之前创建的连接是否成功,可以检查数据库对象是否为null:
if(!db)
alert("Failed to connect to database.");
( 注意:使用中绝不可以假设该连接已经成功建立,即使过去对于某个用户它是成功的。为什么一个连接会失败,这里面存在多个原因:也许浏览器出于安全原因拒绝访问,也许设备存储有限。面对活跃而快速进化的潜在浏览器,对用户机器、软件及其能力作出假设是非常不明智的行为。如当用户使用手持设备时,他们可自由处置的数据可能只有几兆字节。
2.访问和操作数据库
实际访问数据库时,还需要调用transaction()方法,用来执行事务处理。使用事务处理,可以防止在对数据库进行访问及执行有关操作时受到外界的打扰。因为在Web上,同时会有许多人都在对页面进行访问。如果在访问数据库的过程中,正在操作的数据被别的用户给修改掉,会引起很多意想不到的后果。因此,可以使用事务来达到在操作完了之前,阻止别的用户访问数据库的目的。
transaction()方法的使用方法如下:
db.transaction( function(tx) {})
transaction()方法使用一个回调函数作为参数。在这个函数中,执行访问数据库的语句。
在transaction()方法的回调函数内,使用了作为参数传递给回调函数的transaction对象的executeSql()方法。executeSql()方法的完整定义如下:
transaction.executeSql(sqlquery,[],dataHandler, errorHandler):
该方法使用4个参数,第一个参数为需要执行的SQL语句。
第二个参数为SQL语句中所有使用到的参数的数组。在executeSql()方法中,将SQL语句中所要使用到的参数先用“?”代替,然后依次将这些参数组成数组放在第二个参数中,如下所示:
transaction.executeSql("UPDATE people set age-? where name=?;",[age, name]);
第三个参数为执行SQL语句成功时调用的回调函数。该回调函数的传递方法如下:
function dataRandler(transaction, results){//执行SQL语句成功时的处理
}
该回调函数使用两个参数,第一个参数为transaction对象,第二个参数为执行查询操作时返回的查询到的结果数据集对象。
第四个参数为执行SQL语句出错时调用的回调函数。该回调函数的传递方法如下:
function errorHandler(transaction,errmeg) {//执行SQL语句出错时的处理
}
该回调函数使用两个参数,第一个参数为transaction对象,第二个参数为执行发生错误时的错误信息文字。
【示例2】下面将在mydatabase数据库中创建表t1,并执行数据插入操作,完成插入两条记录。
var db = openDatabase('mydatabase', '2.0', my db',2*1024);
db.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS t1 (id unique, log)');
tx.executeSql('INSERT INTO t1 (id, log) VALUES (1, "foobar")');
tx.executeSql('INSERT INTO t1 (id, log) VALUES (2, "logmsg")');
});
在插入新记录时,还可以传递动态值:
var db = openDatabase('mydatabase', '2.0', 'my db',2*1024);
db.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS t1 (id unique, log)');
tx.executeSql('INSERT INTO t1 (id,log) VALUES (?, ?'), [e_id, e_log]; //e_id和e_log是外部变量
});
当执行查询操作时,从查询到的结果数据集中依次把数据取出到页面上来,最简单的方法是使用for语句循环。结果数据集对象有一个rows属性,其中保存了查询到的每条记录,记录的条数可以用rows.length来获取,可以用for循环,用rows[index]或rows.Item (index])的形式来依次取出每条数据。在JavaScript脚本中,一般采用rows[index]的形式。另外在Chrome 浏览器中,不支持rows.Item ([index)的形式。
【示例3】要读取已经存在的记录,使用一个回调函数来捕获结果,并通过for语句循环显示每条记录。
var db = openDatabase(mydatabase, '2.0', 'my db', 2*1024); db.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS t1 (id unique, log)');
tx.executeSql('INSERT INTO t1 (id, log) VALUES (1, "foobar")');
tx.executeSql('INSERT INTO t1 (id, log) VALUES (2, "logmsg")');
});
db.transaction(function (tx) {
tx.executeSql('SELECT * FROM t1, [], function (tx, results) {
var len = results.rows.length, i;
msg = "Found rows: " + len + "";
document.querySelector('#status').innerHTML += msg;
for (i = 0; i < len; i++){
alert(results.rows.item(i).log );
}
}, null);
});
19.6.3 实例1:创建简单的本地数据库
本实例将完整地演示Web SQL Database API的使用,包括建立数据库、建立表格、插入数据、查询数据、将查询结果显示。在最新版本的 Chrome、Safari 或 Opera 浏览器中输出结果如图19-6所示。
实例完整代码如下:
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
var msg;
db.transaction(function(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');
tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "foobar")');
tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "logmsg")');
msg = '完成消息创建和插入行操作。';
document.querySelector('#status').innerHTML = msg;
});
db.transaction(function(tx) {
tx.executeSql('SELECT * FROM LOGS', [], function(tx, results) {
var len = results.rows.length, i;
msg = "查询行数: " + len + "";
document.querySelector('#status').innerHTML += msg;
for( i = 0; i < len; i++) {
msg = "" + results.rows.item(i).log + "";
document.querySelector('#status').innerHTML += msg;
}
}, null);
});
其中第五行的var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);建立一个名称为 mydb的数据库,它的版本为1.0,描述信息为Test DB,大小为2MB字节。可以看到此时有数据库建立,但并无表格建立,如图19-7所示。
[pic] [pic]
图19-6 创建简单的本地数据库 图19-7 创建数据库mydb
openDatabase()方法打开一个已经存在的数据库,如果数据库不存在则创建数据库,创建数据库包括数据库名、版本号、描述、数据库大小、创建回调函数。最后一个参数创建回调函数,在创建数据库时调用,但即使没有这个参数,一样可以运行时创建数据库。
第七行到第十三行代码:
db.transaction(function(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');
tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "foobar")');
tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "logmsg")');
msg = '完成消息创建和插入行操作。';
document.querySelector('#status').innerHTML = msg;
});
通过第八行语句可以在mydb数据库中建立一个LOGS表格。在这里只执行创建表格语句,而不执行后面两个插入操作时,在Chrome中可以看到在数据库mydb中有表格LOGS建立,但表格LOGS为空。
第九行、第十行执行插入操作,在插入新记录时,还可以传递动态值:
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
db.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');
tx.executeSql('INSERT INTO LOGS (id,log) VALUES (?, ?'), [e_id, e_log];
});
这里的e_id和e_log为外部变量,executeSql()在数组参数中将每个变量映射到“?”。在插入操作执行后,可以在Chrome中看到数据库的状态,可以看到插入的数据,此时并未执行查询语句,页面中并没有出现查询结果,如图19-8所示。
[pic]
图19-8 创建数据表并插入数据
如果要读取已经存在的记录,使用一个回调函数捕获结果,如上面的第十四行到第二十四行代码:
db.transaction(function(tx) {
tx.executeSql('SELECT * FROM LOGS', [], function(tx, results) {
var len = results.rows.length, i;
msg = "查询行数: " + len + "";
document.querySelector('#status').innerHTML += msg;
for( i = 0; i < len; i++) {
msg = "" + results.rows.item(i).log + "";
document.querySelector('#status').innerHTML += msg;
}
}, null);
});
执行查询之后,将信息输出到页面中,可以看到页面中的查询数据,如图19-6所示。
( 注意:如果不是绝对需要,不要使用Web SQL Database,因为它会让代码更加复杂(匿名内部类的内部函数、回调函数等)。在大多数情况下,本地存储或会话存储就能够完成相应的任务,尤其是能够保持对象状态持久化的情况。通过这些HTML5 Web SQL Database API 接口,可以获得更多功能,相信以后会出现一些非常优秀的、建立在这些 API 之上的应用程序。
19.6.4 实例2:批量存储本地数据
Web SQL Database操作数据比较繁琐,为了提高代码执行效率,下面通过一个示例演示如何通过数组实现快速存储数据。
Web SQL Database
var db = openDatabase('db', '1.0', 'my first database', 2 * 1024 * 1024);
function log(id, name) {
var row = document.createElement("tr");
var idCell = document.createElement("td");
var nameCell = document.createElement("td");
idCell.textContent = id;
nameCell.textContent = name;
row.appendChild(idCell);
row.appendChild(nameCell);
document.getElementById("racers").appendChild(row);
}
function doQuery() {
db.transaction(function (tx) {
tx.executeSql('SELECT * from mytable', [], function(tx, result) {
for (var i=0; i=0; i--){
datatable.removeChild(datatable.childNodes[i]);
}
var tr = document.createElement('tr');
var th1 = document.createElement('th');
var th2 = document.createElement('th');
var th3 = document.createElement('th');
th1.innerHTML = '姓名';
th2.innerHTML = '留言';
th3.innerHTML = '时间';
tr.appendChild(th1);
tr.appendChild(th2);
tr.appendChild(th3);
datatable.appendChild(tr);
}
function showData(row) {
var tr = document.createElement('tr');
var td1 = document.createElement('td');
td1.innerHTML = row.name;
var td2 = document.createElement('td');
td2.innerHTML = row.message;
var td3 = document.createElement('td');
var t = new Date();
t.setTime(row.time);
td3.innerHTML=t.toLocaleDateString()+" "+t.toLocaleTimeString();
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
datatable.appendChild(tr);
}
function showAllData(){
db.transaction(function(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS MsgData(name TEXT, message TEXT, time INTEGER)',[]);
tx.executeSql('SELECT * FROM MsgData', [], function(tx, rs) {
removeAllData();
for(var i = 0; i < rs.rows.length; i++){
showData(rs.rows.item(i));
}
});
});
}
function addData(name, message, time) {
db.transaction(function(tx) {
tx.executeSql('INSERT INTO MsgData VALUES(?, ?, ?)',[name, message, time],function(tx, rs)
{
alert("成功保存数据!");
},
function(tx, error) {
alert(error.source + "::" + error.message);
});
});
}
function saveData(){
var name = document.getElementById('name').value;
var memo = document.getElementById('memo').value;
var time = new Date().getTime();
addData(name,memo,time);
showAllData();
}
使用Web SQL设计Web留言本
姓名:
留言:
下面重点分析JavaScript脚本代码。
← 打开数据库
打开数据库的代码如下:
var datatable = null;
var db = openDatabase('MyData', '', 'My Database', 102400);
在JavaScript脚本一开始,使用了一个变量datatable。用这个变量来代表页面中的table元素。db变量代表使用openDatabase()方法创建的数据库访问对象。在示例中创建了MyData数据库并对其进行访问。
← 初始化
编写init()函数,该函数在页面打开时调用。为了在打开页面时就往页面表格中装入数据,所以在该函数中首先设定变量datatable为页面中的表格,然后调用脚本中另一个函数showAllData()来显示数据。
← 清除表格中当前显示的数据
removeAllData()函数是在showAllData()函数中被调用的一个必不可少的函数,它的作用是将页面中table元素下的子元素全部清除,只留下一个空表格框架,然后输入表头。这样在页面表格中当前显示的数据就全部被清除,以便重新读取数据并装入表格。
← 显示数据
showData()函数使用一个row参数,该参数表示从数据库中读取到的一行数据。该函数在页面表格中使用tr元素添加一行,并使用td元素添加各列,然后将传入的这行数据分别输入在表格中添加的这一行对应的各列中。
← 显示全部数据
showAllData()函数使用transaction()方法,在该方法的回调函数中执行executeSGL()方法获取全部数据。获取到数据之后,首先调用removeAllData()函数初始化页面表格,将该表格中当前显示的数据全部清除,然后在循环中调用showData()函数,将获取到的每一条数据作为参数传入,在页面上的表格中逐条显示获取到的每条数据。
← 追加数据
addData()函数在saveData()函数中被调用。在addData()函数中,使用transaction()方法,在该方法的回调函数中执行executeSGL()方法,将作为参数传入进来的数据保存在数据库中。
← 保存数据
saveData()函数首先调用addData()函数追加数据,然后调用showAllData()函数重新显示表格中的全部数据。
示例演示效果如图19-12所示。
[pic]
图19-12 使用Web SQL设计Web留言本
[pic]
-----------------------
[pic]
图19-4 Web应用计数器
[pic]
图19-5 Web应用项目实时跟踪
[pic]
图19-9 批量存储本地数据
-----------------------
JavaScript网页编程从入门到精通
Note
Note
第19章 Web存储
................
................
In order to avoid copyright disputes, this page is only a partial summary.
To fulfill the demand for quickly locating and searching documents.
It is intelligent file search solution for home and business.