随着firefox4正式版的推出,IndexedDB正式进入我们的视线。IndexedDB是HTML5-WebStorage的重要一环,是一种轻量级NOSQL数据库。相较之下,WebDataBase标准已经很长时间没有更新,大有被IndexedDB取代的意思。

Section 1:起步,得到Database引用

w3c为IndexedDB定义了很多接口,其中Database对象被定义为IDBDataBase。而得到IDBDataBase用的是工厂方法,即从IDBFactory中取得。浏览器对象中,实现了IDBFactory的只有indexedDB这个实例。

大家可以先看下IDBFactory和IDBDataBase接口的定义

  1. interface IDBFactory {
  2. IDBRequest open (in DOMString name);
  3. IDBRequest deleteDatabase (in DOMString name);
  4. };
  5. interface IDBDatabase : EventTarget {
  6. readonly attribute DOMString     name;
  7. readonly attribute DOMString     version;
  8. readonly attribute DOMStringList objectStoreNames;
  9. IDBObjectStore          createObjectStore (in DOMString name, in optional Object optionalParameters) raises (IDBDatabaseException);
  10. IDBRequest              deleteObjectStore (in DOMString name) raises (IDBDatabaseException);
  11. IDBVersionChangeRequest setVersion ([TreatNullAs=EmptyString] in DOMString version);
  12. IDBTransaction          transaction (in any storeNames, in optional unsigned short mode) raises (IDBDatabaseException);
  13. void                    close ();
  14. attribute Function      onabort;
  15. attribute Function      onerror;
  16. attribute Function      onversionchange;
  17. };
  18. interface IDBRequest : EventTarget {
  19. readonly attribute any            result get raises (IDBDatabaseException);
  20. readonly attribute unsigned short errorCode get raises (IDBDatabaseException);
  21. readonly attribute Object         source;
  22. readonly attribute IDBTransaction transaction;
  23. const unsigned short LOADING = 1;
  24. const unsigned short DONE = 2;
  25. readonly attribute unsigned short readyState;
  26. attribute Function       onsuccess;
  27. attribute Function       onerror;
  28. };

重要:IndexedDB中,几乎所有的操作都是采用了command->request->result的方式。比如查询一条记录,返回一个request,在request的result中得到查询结果。又比如打开数据库,返回一个request,在request的result中得到返回的数据库引用。

从IDBFactory的方法体定义中可以看到,返回了一个IDBRequest对象。这个IDBRequest就是刚才所说的request。

下面给出一个通用的得到IDBDataBase的方法

  1. if (!window.indexedDB) {
  2. window.indexedDB = window.mozIndexedDB || window.webkitIndexedDB;
  3. }
  4. var request = indexedDB.open("MyTestDatabase");
  5. request.onsuccess = function(e) {
  6. // Obtain IDBDatabase
  7. // VERSION_CHANGE transaction callback
  8. var db = request.result;
  9. }

Firefox4中使用IndexedDB的注意点:

1.indexedDB这个实例并不叫indexedDB,而是叫mozIndexedDB

2.indexedDB无法在iframe或者frame标签中使用

3.Firefox4中并未实现deleteDatabase方法(可能会在新版本中改进)

4.indexedDB.open并不能简单的看成是打开数据库,而是在打开数据库的基础上启动了一个version_change事件方法回调。在这个回调方法里自动启动了一个事务,用于version_change。IDBDatabase对象必须要在这个事务中才能取得。

Section 2:初始化object store

indexedDB标准建议,在初始化的时候创建表。以后每次打开浏览器,只需要check版本号。不需要第二次创建。而表在indexedDB中被称为object store。

下面给出object store接口的定义:

  1. interface IDBObjectStore {
  2. readonly attribute DOMString      name;
  3. readonly attribute DOMString      keyPath;
  4. readonly attribute DOMStringList  indexNames;
  5. readonly attribute IDBTransaction transaction;
  6. IDBRequest put (in any value, in optional any key) raises (IDBDatabaseException, DOMException);
  7. IDBRequest add (in any value, in optional any key) raises (IDBDatabaseException, DOMException);
  8. IDBRequest delete (in any key) raises (IDBDatabaseException);
  9. IDBRequest get (in any key) raises (IDBDatabaseException);
  10. IDBRequest clear () raises (IDBDatabaseException);
  11. IDBRequest openCursor (in optional any range, in optional unsigned short direction) raises (IDBDatabaseException);
  12. IDBIndex   createIndex (in DOMString name, in DOMString keyPath, in optional Object optionalParameters) raises (IDBDatabaseException);
  13. IDBIndex   index (in DOMString name) raises (IDBDatabaseException);
  14. void       deleteIndex (in DOMString indexName) raises (IDBDatabaseException);
  15. };

大家可以看到IDBDatabase中有一个createObjectStore方法。但是取得IDBDatabase后直接调用会报Exception。原因在于createObjectStore不能在version_change 的transaction callback中被调用。

下面给出通用的创建object store的代码

  1. var db = null;
  2. var customerData = [
  3. {ssn: "444-44-4444", name: "Bill", age: 25, email: "bill@company.com", nickName: ["1", "2", "3"]},
  4. {ssn: "555-55-5555", name: "Donna", age: 34, email: "donna@home.org"},
  5. {ssn: "666-66-6666", name: "Jack", age: 14, email: "jack@sina.com.cn"}
  6. ];
  7. request.onsuccess = function(e) {
  8. // Obtain IDBDatabase
  9. // VERSION_CHANGE transaction callback
  10. db = request.result;
  11. if (db.version != "1.0") {
  12. var requestVersion = db.setVersion("1.0");
  13. requestVersion.onerror = function(event) {
  14. alert(event);
  15. }
  16. requestVersion.onsuccess = function(event) {
  17. createObjectStore(db);
  18. }
  19. }
  20. db.close();
  21. };
  22. function createObjectStore(db) {
  23. if (db.objectStoreNames.contains('customers')) {
  24. db.deleteObjectStore("customers")
  25. }
  26. // Create Object Store
  27. // This method was not called from a VERSION_CHANGE transaction callback.
  28. var objectStore = db.createObjectStore("customers", {
  29. // primary key
  30. keyPath: "ssn",
  31. // auto increment
  32. autoIncrement: false
  33. });
  34. objectStore.createIndex("name", "name", { unique: false });
  35. objectStore.createIndex("email", "email", { unique: true });
  36. // Add initial data
  37. for (var index = 0; index < customerData.length; index++) {
  38. objectStore.add(customerData[index]);
  39. }
  40. }

以上代码创建了一个名为customers,PrimaryKey为ssn,并且不带自增序列的object store(表)。并为这个object store创建了两个索引(name和email).其中email是唯一键。并且为customers创建了初始数据。可以看到初始数据中可以嵌套多层结构。

Section 3:事务和游标

通过上面IDBDatabase接口的定义,我们可以从IDBDatabase中取得transaction。在indexedDB中,事务会自动提交或回滚。所以无需手动commit或者rollback。

事务分为三种

IDBTransaction.READ_ONLY              只读

IDBTransaction.READ_WRITE            可读可写

IDBTransaction.VERSION_CHANGE    版本升级

我们用的最多的是前两种。如果不设置事务级别,则默认为READ_ONLY。

游标是遍历object store的唯一方法。虽然firefox4中有getAll,但是相信在不久的将来,这个方法会被取缔。

如果在打开游标的时候不设置,默认采用IDBCursor.NEXT

下面给出得到事务对象的通用方法

  1. // 通过IDBDatabase得到IDBTransaction
  2. var transaction = db.transaction(["customers"]);
  3. // 通过IDBTransaction得到IDBObjectStore
  4. var objectStore = transaction.objectStore("customers");
  5. // 打开游标,遍历customers中所有数据
  6. objectStore.openCursor().onsuccess = function(event) {
  7. var cursor = event.target.result;
  8. if (cursor) {
  9. var key = cursor.key;
  10. var rowData = cursor.value;
  11. alert(rowData.name);
  12. cursor.continue();
  13. }
  14. }

上面代码中使用了游标,这里要注意,在调用了cursor.continue之后,cursor会重新调用onsuccess句柄上的方法。所以,以上代码的onsuccess实际上被调用了3遍。至于openCursor的使用方法,下个Section中会有提到

Section 4:索引查询

section3中的objectStore.openCursor是根据keyPath去查询的。如果想通过某个索引去查询,可以用objectStore.index(索引名).openCursor去查询

1)openCursor的第一个参数为查询条件,他需要传入一个IDBKeyRange对象。

IDBKeyRange的创建方式有4种,都是调用了IDBKeyRange的静态方法。分别代表了4种不同类型的条件。

  1. // 只取得当前索引的值为Bill的数据
  2. IDBKeyRange.only("Bill");
  3. // 只取得当前索引的值大于Bill,并且不包括Bill的数据
  4. IDBKeyRange.lowerBound("Bill", true);
  5. // 只取得当前索引的值小于Bill,并且包括Bill的数据
  6. IDBKeyRange.upperBound("Bill", false);
  7. // 取得当前索引的值介于Bill和Jack之间,并且包括Bill,但不包括Jack的数据
  8. IDBKeyRange.bound("Bill", "Jack", false, true);

2)openCursor的第二个参数为游标方向。有4种

IDBCursor.NEXT                                  顺序循环

IDBCursor.NEXT_NO_DUPLICATE        顺序循环不重复

IDBCursor.PREV                                  倒序循环

IDBCursor.PREV_NO_DUPLICATE        倒序循环不重复

例子:

  1. var boundKeyRange = IDBKeyRange.upperBound("Jack", false);
  2. objectStore.index("name").openCursor(boundKeyRange, IDBCursor.PREV_NO_DUPLICATE).onsuccess = function(event) {
  3. var cursor = event.target.result;
  4. if (!cursor) {
  5. return;
  6. }
  7. var rowData = cursor.value;
  8. alert(rowData.name);
  9. cursor.continue();
  10. };

完整实例请参考附件。注意,indexedDB必须要在发布环境(web容器)中才可以运行。

HTML5之IndexedDB使用详解的更多相关文章

  1. 免费的HTML5连载来了《HTML5网页开发实例详解》连载(二)

    最近新浪.百度.腾讯.京东.大众点评.淘宝等流行的网站都加大了招聘HTML5的力度,HTML5开发人员成了抢手货,本次连载的是由大众点评前端工程师和一淘网前端工程师基情奉献的<HTML5网页开发 ...

  2. 免费的HTML5连载来了《HTML5网页开发实例详解》连载(六)媒体查询

    响应式设计的另一个重要技术手段是媒体查询.如果只是简单的设计一个流式布局系统,那么可以保证每个网格按比例的放大和缩小,但有可能会使得在小屏幕下(如手机设备)网格太小而严重影响阅读,这样的设计称不上响应 ...

  3. 免费的HTML5连载来了《HTML5网页开发实例详解》连载(五)图解通过Fiddler加速开发

    Fiddler是Windows底下最强大的请求代理调试工具,监控任何浏览器的HTTP/HTTPS流量,窜改客户端请求和服务器响应,解密HTTPS Web会话,图4.44为Fiddler原理示意图. 图 ...

  4. 《HTML5网页开发实例详解》连载(四)HTML5中的FileSystem接口

    HTML 5除了提供用于获取文件信息的File对象外,还添加了FileSystem相关的应用接口.FileSystem对于不同的处理功能做了细致的分类,如用于文件读取和处理的FileReader和Fi ...

  5. 免费的HTML5连载来了《HTML5网页开发实例详解》连载(三)DOCTYPE和字符集

    在2.1.2节中通过新老DOCTYPE的对比,读者可以清晰地看到HTML 5在精简旧有结构上做出的努力.DOCTYPE在出现之初主要用于XML中,用作描述XML允许使用的元素.属性和排列方式.起初HT ...

  6. 当里个当,免费的HTML5连载来了《HTML5网页开发实例详解》连载(一)

    读懂<HTML5网页开发实例详解>这本书 你还在用Flash嘛?帮主早不用了 乔布斯生前在公开信“Flash之我见”中预言:像HTML 5这样在移动时代中创立的新标准,将会在移动设备上获得 ...

  7. html5中output元素详解

    html5中output元素详解 一.总结 一句话总结: output元素是HTML5新增的元素,用来设置不同数据的输出,没什么大用,了解即可 <form action="L3_01. ...

  8. html5的datalist元素详解

    html5的datalist元素详解 一.总结 一句话总结: datalist元素配合input元素可以出现有提示选择作用的选框效果,还是相对比较简便好用的 1.optgroup元素是干嘛的? opt ...

  9. html5中section元素详解

    html5中section元素详解 一.总结 一句话总结: section元素 用来定义文章中的章节(通常应该有标题和段落内容) section元素的作用就是给内容分段,给页面分区 1.section ...

随机推荐

  1. .NET 跨平台RPC框架DotNettyRPC Web后台快速开发框架(.NET Core) EasyWcf------无需配置,无需引用,动态绑定,轻松使用 C# .NET 0配置使用Wcf(半成品) C# .NET Socket 简单实用框架 C# .NET 0命令行安装Windows服务程序

    .NET 跨平台RPC框架DotNettyRPC   DotNettyRPC 1.简介 DotNettyRPC是一个基于DotNetty的跨平台RPC框架,支持.NET45以及.NET Standar ...

  2. DBA_实践指南系列11_Oracle Erp R12性能调优基础(案例)

    http://www.itpub.net/thread-1412437-1-1.html

  3. Go 普通LOG输出

    因为Go 语言中没有自带的宏, 来表示行号和文件, 需要从方法中去获取,麻烦.所以封装了一个函数,用于输出平时程序的打印日志 import ( "fmt" "log&qu ...

  4. Linux中网络通信中 使用的结构体

    "+++++++++++++++++++++++++ Linux TCP/UDP通信中的结构体 +++++++++++++++++++++++++++++++++++++++" s ...

  5. 易懂的modelsim学习笔记

    1. 建一个总文件夹,如cnt2. 为源代码,测试台文件,仿真各建一文件夹.如src,tb,sim3. 编写源代码,testbench.如cnt.v,tb_cnt.v文件,同时文件名里的模块名与文件名 ...

  6. [svc]centos7安装优化最佳姿势

    源/软件/时区/selinux/ulimit/vim/sshd 下载安装: https://mirrors.aliyun.com/centos/7.4.1708/isos/x86_64/CentOS- ...

  7. 【Android】Java堆栈溢出的解决办法

    分类:C#.Android.VS2015: 创建日期:2016-03-18 随着项目中添加的.jar和.so文件越来越多,编译MyDemos项目时,可能会出现Java堆栈溢出的错误,提示让增加Java ...

  8. HAProxy负载均衡原理及企业级实例部署haproxy集群

    一 HAProxy简介   HAProxy是一种高效.可靠.免费的高可用及负载均衡解决方案,非常适合于高负载站点的七层数据请求.客户端通过HAProxy代理服务器获得站点页面,而代理服务器收到客户请求 ...

  9. JDK自带工具之问题排查场景示例

    最近看到了大量关于java性能调优.故障排查的文章,自己也写了一篇< Java调优经验谈 >.接着此篇文章,其实一直打算写写一些常用调优工具以及它们的惯常用法的.后来在http://jav ...

  10. Date函数基础知识整理

    Date类型:1.Date.parse()接收一个表示日期的字符串参数,然后再根据这个字符串返回响应的日期的毫秒数:如:创建一个日期: <script> // var someDate=n ...