本地数据库

*:first-child {
margin-top: 0 !important;
}

body>*:last-child {
margin-bottom: 0 !important;
}

/* BLOCKS
=============================================================================*/

p, blockquote, ul, ol, dl, table, pre {
margin: 15px 0;
}

/* HEADERS
=============================================================================*/

h1, h2, h3, h4, h5, h6 {
margin: 20px 0 10px;
padding: 0;
font-weight: bold;
-webkit-font-smoothing: antialiased;
}

h1 tt, h1 code, h2 tt, h2 code, h3 tt, h3 code, h4 tt, h4 code, h5 tt, h5 code, h6 tt, h6 code {
font-size: inherit;
}

h1 {
font-size: 28px;
color: #000;
}

h2 {
font-size: 24px;
border-bottom: 1px solid #ccc;
color: #000;
}

h3 {
font-size: 18px;
}

h4 {
font-size: 16px;
}

h5 {
font-size: 14px;
}

h6 {
color: #777;
font-size: 14px;
}

body>h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h4:first-child, body>h5:first-child, body>h6:first-child {
margin-top: 0;
padding-top: 0;
}

a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
margin-top: 0;
padding-top: 0;
}

h1+p, h2+p, h3+p, h4+p, h5+p, h6+p {
margin-top: 10px;
}

/* LINKS
=============================================================================*/

a {
color: #4183C4;
text-decoration: none;
}

a:hover {
text-decoration: underline;
}

/* LISTS
=============================================================================*/

ul, ol {
padding-left: 30px;
}

ul li > :first-child,
ol li > :first-child,
ul li ul:first-of-type,
ol li ol:first-of-type,
ul li ol:first-of-type,
ol li ul:first-of-type {
margin-top: 0px;
}

ul ul, ul ol, ol ol, ol ul {
margin-bottom: 0;
}

dl {
padding: 0;
}

dl dt {
font-size: 14px;
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px;
}

dl dt:first-child {
padding: 0;
}

dl dt>:first-child {
margin-top: 0px;
}

dl dt>:last-child {
margin-bottom: 0px;
}

dl dd {
margin: 0 0 15px;
padding: 0 15px;
}

dl dd>:first-child {
margin-top: 0px;
}

dl dd>:last-child {
margin-bottom: 0px;
}

/* CODE
=============================================================================*/

pre, code, tt {
font-size: 12px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}

code, tt {
margin: 0 0px;
padding: 0px 0px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px;
}

pre>code {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent;
}

pre {
background-color: #f8f8f8;
border: 1px solid #ccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px;
}

pre code, pre tt {
background-color: transparent;
border: none;
}

kbd {
-moz-border-bottom-colors: none;
-moz-border-left-colors: none;
-moz-border-right-colors: none;
-moz-border-top-colors: none;
background-color: #DDDDDD;
background-image: linear-gradient(#F1F1F1, #DDDDDD);
background-repeat: repeat-x;
border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD;
border-image: none;
border-radius: 2px 2px 2px 2px;
border-style: solid;
border-width: 1px;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
line-height: 10px;
padding: 1px 4px;
}

/* QUOTES
=============================================================================*/

blockquote {
border-left: 4px solid #DDD;
padding: 0 15px;
color: #777;
}

blockquote>:first-child {
margin-top: 0px;
}

blockquote>:last-child {
margin-bottom: 0px;
}

/* HORIZONTAL RULES
=============================================================================*/

hr {
clear: both;
margin: 15px 0;
height: 0px;
overflow: hidden;
border: none;
background: transparent;
border-bottom: 4px solid #ddd;
padding: 0;
}

/* TABLES
=============================================================================*/

table th {
font-weight: bold;
}

table th, table td {
border: 1px solid #ccc;
padding: 6px 13px;
}

table tr {
border-top: 1px solid #ccc;
background-color: #fff;
}

table tr:nth-child(2n) {
background-color: #f8f8f8;
}

/* IMAGES
=============================================================================*/

img {
max-width: 100%
}
-->

本地数据库

本地数据库概念

HTML5 的一个重要特性是本地数据持久性,结合应用程序缓存能够实现离线状态下的正常工作。此外,本地数据持久性使移动应用程序更灵敏,使用的带宽更少,而且能够在低带宽场景中更高效地工作。HTML5 提供了一些本地数据持久性选项。第一个选项是 localstorage,它支持您使用一个简单的键值对来存储数据。IndexedDB支持您本地存储大量对象,并使用健壮的数据访问机制检索数据。我们这一节就讲解indexedDB

判断浏览器是否支持

indexedDB是window中的对象,所以使用下面的代码判断

 //判断浏览器是否支持本地存储
if (window.indexedDB) {
alert("支持");
} else {
alert("不支持");
}

新建数据库

使用open方法新建数据库,代码如下

var request = window.indexedDB.open("数据库名称", 版本号);

open方法的作用

open方法的作用是新建或者打开数据库,如果指定的数据库不存在,则创建数据库;如果已经存在,则打开数据库

open方法参数

open方法接受两个参数

  • 第一个参数是数据库名称。因为一个网站可以有多个本地数据库,所以要保证这个数据库名称是唯一的
  • 第二个参数是数据库版本号。每一次改变数据库的结构,比如添加、修改、删除存储对象(表),都要变更版本号

这里我们着重说一下版本号的注意点。

  • 版本号只能增,不能减。比如上次调用open方法,传入的版本号是2,再次调用的时候修改为1,则会报错
  • 版本号可以为空。当版本号为空时,创建的数据库的版本号为1

实例

运行如下代码

if (window.indexedDB) {
//注意我们没有写版本号,则默认为1
var request= window.indexedDB.open("db1");
} else {
alert("不支持");
}

下面我们来看看数据库是否创建成功,以chrome为例,按下F12或者Fn+F12,打开开发者工具,选择“Resources”选项卡

我们看到左侧的indexedDB,展开来看看

这个db1就是我们刚刚创建的数据库,右边展示的是数据库的信息,分别说明了数据库所属的域,名称以及版本号

这是如果我们再次执行上面的代码,则不会再次创建db1数据库,而是打开,因为此数据库已经存在

修改上面的代码,将版本号改为2

 if (window.indexedDB) {
//注意我们没有写版本号,则默认为1
var request= window.indexedDB.open("db1",2);
} else {
alert("不支持");
}

再次执行这段代码,看开发者工具中indexedDB变化(注意,要刷新之后才能看到变化。刷新方法:在indexedDB上右键-“Refresh indexedDB”)

但是如果现在想再次升级数据库版本,则应将数据库的版本号修改为>2的数字,如果改为<2的数字,比如1,则不会有任何作用

获取创建的数据库

数据库创建好之后,我们需要拿到创建的数据库的引用才能够操作数据库,如创建objectstore(表),操作数据等。

我们注意到open方法的返回值 request 了吗?但是它并是数据库的引用,open方法只是向浏览器发送了一个请求,请求新建或打开某个数据库,对象request有三个重要的事件,我们可以在这些事件中根据不同的情况编写不同的代码,首先我们熟悉一下这几个事件

  • onerror:当调用open方法发生错误时,会调用这个事件,如open方法中的版本号低于数据库的版本号
  • onsuccess:open方法成功执行时调用,如成功新建了数据库,或者成功打开了已有的数据库
  • onupgradeneeded:此事件只有在新建数据库和数据库版本号发生变化时才被调用。注意:此事件发生在onsuccess事件之前

总结:应该将对objectstroe的操作,如创建、修改、删除操作放在onupgradeneeded事件中,而不能放在onsuccess事件中,这些操作数据数据库结构的变更,属于升级操作,而onsuccess事件每次open方法都会执行,也会调用open方法的目的只是为了添加一条数据而已。

下面我们来编写完整的代码

window.onload = function() {
//声明变量用来存储数据库的引用
var mydb;
//判断浏览器是否支持本地存储
if (window.indexedDB) {
//注意我们没有写版本号,则默认为1
var request = window.indexedDB.open("db1", 2);
request.onerror = function(e) {
console.log("打开数据库时发生错误");
};
request.onsuccess = function(e) {
mydb = e.target.result;
console.log("打开数据库成功");
};
request.onupgradeneeded = function(e) {
mydb = e.target.result;
console.log("数据库版本变更成功");
};
} else {
alert("不支持");
}
}

console.log方法是为了在控制台中输出内容,用来调试

e.target.result获取的就是对数据库的引用,我们声明了一个全局变量mydb来存储这个引用。

这是使用indexedDB数据库一个比较完整的结构,接下来我们就创建objectStore

创建objectStore

objectStore概念

有了数据库后我们自然希望创建一个表用来存储数据,但indexedDB中没有表的概念,而是objectStore,我自己翻译成对象仓库,一个数据库中可以包含多个objectStore,objectStore是一个灵活的数据结构,可以存放多种类型数据。也就是说一个objectStore相当于一张表,里面存储的每条数据和一个键相关联。

那么这个键是什么呢?

键为何物

在objectStore中数据的存储方式与传统的关系型数据库不一样。比如要存储下面的信息

一个人的姓名是张三,年龄是20,性别是男,籍贯是保定

传统的关系型数据库的存储方式是这这样的:首先在表中创建字段,然后再每个字段下面添加值(鉴于每张表必须要有主键的原则,我们还必须为其添加一个业务无关列,比如 id),如下图

id name age gender address
1 张三 20 保定

好,这个id列就相当于objectstore中的键,目的是为了唯一标识每条数据。

但是在objectstore中数据的表示形式不是这样的,而是以键值对的形式存储数据

{name:"张三",age:20,gender:"男",address:"保定"}

我们会思考,如果还有另外一条一模一样的数据怎么办(同名同姓、想同年级、相同性别、相同籍贯的人太多了),如果某一天我们要找张三,到底找哪个呢?

所以在objectstore中也有键的概念,我们一起来看一下在indexedDB中,应该如何指定键

在indexedDB中,键有如下类型

键类型 存储数据
不使用 任意值,但是没添加一条数据的时候需要指定键参数
keyPath Javascript对象,对象必须有一属性作为键值
keyGenerator 任意值
都使用 Javascript对象,如果对象中有keyPath指定的属性则不生成新的键值,如果没有自动生成递增键值,填充keyPath指定属性

大家不要晕,今天我们只介绍一种,keyPath,剩下的大家自己就能看懂了。keyPath的意思就是使用每条记录中的某个指定字段作为键值(keyPath),比如上面的数据

{name:"张三",age:20,gender:"男",address:"保定"}

我们修改一下,新增一个id

{id:"1001",name:"张三",age:20,gender:"男",address:"保定"}

我们将id的值作为唯一标识这条数据的键,就可以使用keyPath方式,具体使用方式在创建objectstore的使用会介绍

创建objectstore

修改onupgradeneeded事件中的代码

 request.onupgradeneeded = function(e) {
mydb = e.target.result;
if (!mydb.objectStoreNames.contains("student")) {
mydb.createObjectStore("student", {
keyPath: "id"
});
};
};

mydb.objectStoreNames.contains方法用来判断数据库中是否存在名称为 student 的objectstore,如果没有则创建

createObjectStore方法用来创建objectstore,其接受两个参数,第一个参数是objectstore名称,第二个是为这个objectstore指定键的值,{keyPath: "id"}的意思是student采用keyPath类型的键,这个键的值就是数据库中id字段的值

当然,在执行这段代码之前,别忘了修改open方法中的版本号,否则这个事件是不会执行的(怎么样,被我说中了吧)

看下图(别忘了右键刷新)

也许现在你对这个“键”的概念还不是很清楚,没事,下面我们插入两条数据,一看数据你就明白了

向objectstore中插入数据

事务

在对数据进行操作之前(注意不是对数据库),需要开始一个事务。事务中需要指定该事务跨越哪些object store。也就是说,任何对objectstore中的数据的操作都要放在事务当中

事务具有三种模式

  • 只读:read,不能修改数据库数据,可以并发执行
  • 读写:readwrite,可以进行读写操作
  • 版本变更:verionchange

下面我们看代码如何实现

在html中加入一个按钮,点击此按钮式向名为student的objectstore插入数据

<body>
<input type="button" name="btnAdd" id="btnAdd" value="插入数据">
</body>

为此按钮添加单击事件,代码如下

document.getElementById("btnAdd").onclick = function() {
//创建要添加的数据
var student = {
id:"1001",
name: "张三",
age: 20,
gender: "男",
address: "保定"
};
//创建针对student的事务
var transaction = mydb.transaction(["student"], "readwrite");
//从事务中获取要操作的objectstore
var obj = transaction.objectStore("student");
//添加数据
obj.add(student);
console.log("数据添加成功");
}

我们拼接了一个键值对的集合,其作为要插入到student中数据,因为objectstore只接受这种格式的数据,请先记住id的值

mydb.transaction方法用来开启事务,其接受两个参数,第一个是与这个事务相关联的objectstore的名称,注意使用了[],因为一个事务可以关联多个objectstore,第二个参数说明此事务是可读可写的,即可以在这个事务中读写数据

transaction.objectStore("student")方法在事务中获取要操作的objectstore

obj.add(student)方法用来向objectstore中插入数据

点击按钮后,刷新indexedDB,查看结果

我们看到,key的值就是键值对中id的值

添加多条数据

如果想添加多条数据,我们就需要修改一下代码

 document.getElementById("btnAdd").onclick = function() {
//创建要添加的数据
var student = [{
id: "1002",
name: "张三",
age: 20,
gender: "男",
address: "保定"
}, {
id: "1003",
name: "李四",
age: 21,
gender: "男",
address: "国际庄"
}, {
id: "1004",
name: "李丹",
age: 22,
gender: "女",
address: "保定"
}];
//创建针对student的事务
var transaction = mydb.transaction(["student"], "readwrite");
//从事务中获取要操作的objectstore
var obj = transaction.objectStore("student");
//添加数据
for (var i = 0; i < student.length; i++) {
obj.add(student[i]);
};
console.log("数据添加成功");
}

效果如图

思考:为什么这次id的值从1002开始,而不是1001?自己试试

查询数据

这里的查询只能根据key的值查询,不能像传统的数据库那样,可以根据任意一个键值,如name、age等查询,如果要实现这种效果的话,需要配合indexedDB中的索引和游标使用

我们首先讲解根据key值查询

添加一个按钮,用于查询数据

document.getElementById("btnQuery").onclick = function() {
var transaction = mydb.transaction(["student"], "readwrite");
var obj = transaction.objectStore("student");
var request = obj.get("1002");
request.onsuccess = function() {
console.log("id为1002的人的姓名为" + request.result.name);
}
}

obj.get方法的作用是向数据库中的名称为student的objectstore请求键的值为1002对应的数据,请求的结果存储在request.result属性当中。

然后我们再onsuccess事件中获取name的值。

我们可以输出request.result的值看看

request.onsuccess = function() {
//console.log("id为1002的人的姓名为" + request.result.name);
console.log(request.result);
}

结果如下

更新数据

添加一个按钮,用于更新数据,代码非常简单,直接上代码

document.getElementById("btnUpdate").onclick = function() {
var transaction = mydb.transaction(["student"], "readwrite");
var obj = transaction.objectStore("student");
var request = obj.get("1002");
request.onsuccess = function() {
request.result.name="哈哈";
obj.put(request.result);
}
}

与查询方法很想,仍然需要在onsuccess事件中操作,首先更改request.result.name的值为新值,然后使用obj对象的put方法更新数据库

查看结果,发现值已经更改

删除数据

删除数据是最简单的

document.getElementById("btndel").onclick = function() {
var transaction = mydb.transaction(["student"], "readwrite");
var obj = transaction.objectStore("student");
obj.delete("1002");
}

结果如图

删除数据库

数据库也是可以删除的

document.getElementById("btndeldb").onclick = function() {
//关闭数据库连接
mydb.close();
indexedDB.deleteDatabase("db1");
}

删除之前应先调用close方法关闭当前的数据库连接,然后调用indexedDB.deleteDatabase方法根据数据库的名称删除即可

完整的案例

下面提供完整的案例,注意,第一次运行时应将数据库的版本号改为1

<!DOCTYPE html>
<html> <head>
<title>本地数据库</title>
<script type="text/javascript">
window.onload = function() {
//声明变量用来存储数据库的引用
var mydb;
//判断浏览器是否支持本地存储
if (window.indexedDB) {
//注意我们没有写版本号,则默认为1
var request = window.indexedDB.open("db1", 3);
request.onerror = function(e) {
console.log("打开数据库时发生错误");
};
request.onsuccess = function(e) {
mydb = e.target.result;
console.log("打开数据库成功");
};
request.onupgradeneeded = function(e) {
mydb = e.target.result;
if (!mydb.objectStoreNames.contains("student")) {
mydb.createObjectStore("student", {
keyPath: "id"
});
};
};
} else {
alert("不支持");
}
//添加数据
document.getElementById("btnAdd").onclick = function() {
//创建要添加的数据
var student = [{
id: "1002",
name: "张三",
age: 20,
gender: "男",
address: "保定"
}, {
id: "1003",
name: "李四",
age: 21,
gender: "男",
address: "国际庄"
}, {
id: "1004",
name: "李丹",
age: 22,
gender: "女",
address: "保定"
}];
//创建针对student的事务
var transaction = mydb.transaction(["student"], "readwrite");
//从事务中获取要操作的objectstore
var obj = transaction.objectStore("student");
//添加数据
for (var i = 0; i < student.length; i++) {
obj.add(student[i]);
};
console.log("数据添加成功");
}
//查询数据
document.getElementById("btnQuery").onclick = function() {
var transaction = mydb.transaction(["student"], "readwrite");
var obj = transaction.objectStore("student");
var request = obj.get("1002");
request.onsuccess = function() {
console.log("id为1002的人的姓名为" + request.result.name);
}
} //更新数据
document.getElementById("btnUpdate").onclick = function() {
var transaction = mydb.transaction(["student"], "readwrite");
var obj = transaction.objectStore("student");
var request = obj.get("1002");
request.onsuccess = function() {
request.result.name="哈哈";
obj.put(request.result);
}
}
//删除数据
document.getElementById("btndel").onclick = function() {
var transaction = mydb.transaction(["student"], "readwrite");
var obj = transaction.objectStore("student");
obj.delete("1002");
}
document.getElementById("btndeldb").onclick = function() {
//关闭数据库连接
mydb.close();
indexedDB.deleteDatabase("db1");
}
}
</script>
</head> <body>
<input type="button" name="btnAdd" id="btnAdd" value="插入数据">
<input type="button" name="btnQuery" id="btnQuery" value="查询数据">
<input type="button" name="btnUpdate" id="btnUpdate" value="更新数据">
<input type="button" name="btndel" id="btndel" value="删除数据">
<input type="button" name="btndeldb" id="btndeldb" value="删除数据库">
</body> </html>

参考资料

http://www.cnblogs.com/smileberry/p/3844269.html

http://www.cnblogs.com/dolphinX/p/3415761.html

http://www.ibm.com/developerworks/cn/web/wa-indexeddb/

http://www.thinksaas.cn/group/topic/349664/

html5本地数据库(一)的更多相关文章

  1. HTML5本地数据库(SQLite)示例

    本文转载自http://blog.sina.com.cn/s/blog_641cf27f01016pm5.html 按照国内一HTML5先行者的例子仿写了一个用HTML5 API来操作本地SQLite ...

  2. HTML5本地数据库(WebSQL)[转]

    除了sessionStorage和localStorage外,HTML5还支持通过本地数据库进行本地数据存储,HTML5采用的是"SQLite"这种文件型数据库,该数据库多集中在嵌 ...

  3. (转)HTML5 本地数据库(SQLite) 示例

      HTML5 本地数据库(SQLite) 示例 2012-05-07 16:21:13 标签:SQLite HTML5本地数据库 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作 ...

  4. 【HTML5】HTML5本地数据库(Web Sql Database)

    Web Sql数据库简介 Web SQL数据库API实际上不是HTML5规范的组成部分,而是单独的规范.它通过一套API来操纵客户端的数据库. Web SQL数据库的浏览器支持情况 Web SQL 数 ...

  5. HTML5 本地数据库(SQLite) 示例

    http://supercharles888.blog.51cto.com/609344/856071 http://www.sqlite.org/download.html

  6. HTML5教程之html 5 本地数据库(Web Sql Database)

    HTML5的Web SQL Databases(html5 本地数据库)的确很诱惑人,当你发现可以用与mysql查询一样的查询语句来操作本地数据库时,你会发现这东西挺有趣的.今天,我们一起来了解HTM ...

  7. Html5 学习系列(六)Html5本地存储和本地数据库

    一个网站如何能在客户的浏览器存储更多的数据呢? 在Html4的时代在浏览器端存储点网站个性化的数据,尤其是用户浏览器的痕迹,用户的相关数据等一般只能存储在Cookie中,但是大多是浏览器对于Cooki ...

  8. HTML5笔记3——Web Storage和本地数据库

    上一篇:HTML5笔记2——HTML5音/视频标签详解 Web Storage概述 在HTML5中,除了Canvas元素之外,另一个新增的非常重要的功能是可以再客户端本地保存数据的Web Storag ...

  9. Html5本地存储和本地数据库

    一个网站如何能在客户的浏览器存储更多的数据呢? 在Html4的时代在浏览器端存储点网站个性化的数据,尤其是用户浏览器的痕迹,用户的相关数据等一般只能存储在Cookie中,但是大多是浏览器对于Cooki ...

随机推荐

  1. ZOJ Problem Set - 3758 素数

    Singles' Day Time Limit: 2 Seconds Memory Limit: 65536 KB Singles' Day(or One's Day), an unofficial ...

  2. MacOS下的生活——RescueTime,时间规划利器

    前段时间Yxj同学给我推荐了一款可以记录电脑及手机使用时间分类的软件,据说Mac平台下也支持,当时就有了兴趣,但是好像因为什么事给耽搁了,知道今天下午看到Yxj在看这个软件记录的自己的时间表,才觉得这 ...

  3. windows下安装python的C扩展编译环境(解决“Unable to find vcvarsall.bat”)

    个人文章除注明转载外,均为个人原创或者翻译. 个人文章欢迎各种形式的转载,但请18岁以上的转载者注明文章出处,尊重我的劳动,也尊重你的智商: 本文链接:http://www.cnblogs.com/f ...

  4. Top 10 Java Debugging Tips with Eclipse

    In this tutorial we will see about debugging java applications using Eclipse. Debugging helps us to ...

  5. hud 1241 dfs连同块

    Problem Description The GeoSurvComp geologic survey company is responsible for detecting underground ...

  6. mvcc摘抄

    MVCC浅析原文:---->>>>>> http://blog.csdn.net/chosen0ne/article/details/18093187 在并发读写数 ...

  7. [kuangbin带你飞]专题十 匹配问题 二分图多重匹配

    二分图的多重匹配问题不同于普通的最大匹配中的"每个点只能有最多一条边" 而是"每个点连接的边数不超过自己的限定数量" 最大匹配所解决的问题一般是"每个 ...

  8. Python自带的日志模块logging的使用

    import logging     # 创建一个logger logger = logging.getLogger('cmccLogger') logger.setLevel(logging.DEB ...

  9. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(4)-构建项目解决方案 创建EF DataBase Frist模式

    原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(4)-构建项目解决方案 创建EF DataBase Frist模式 进行本次文章之前,我们可能需要补充一些 ...

  10. Android中的FrameLayout帧布局

    帧布局由FrameLayout所代表,FrameLayout直接继承了ViewGoup组件. 帧布局容器为每一个增加当中的组件创建一个空白的区域(称为一个帧),每一个子组件占领一帧,这些帧都会依据gr ...