HTML5之IndexedDB使用详解
随着firefox4正式版的推出,IndexedDB正式进入我们的视线。IndexedDB是HTML5-WebStorage的重要一环,是一种轻量级NOSQL数据库。相较之下,WebDataBase标准已经很长时间没有更新,大有被IndexedDB取代的意思。
Section 1:起步,得到Database引用
w3c为IndexedDB定义了很多接口,其中Database对象被定义为IDBDataBase。而得到IDBDataBase用的是工厂方法,即从IDBFactory中取得。浏览器对象中,实现了IDBFactory的只有indexedDB这个实例。
大家可以先看下IDBFactory和IDBDataBase接口的定义
- interface IDBFactory {
- IDBRequest open (in DOMString name);
- IDBRequest deleteDatabase (in DOMString name);
- };
- interface IDBDatabase : EventTarget {
- readonly attribute DOMString name;
- readonly attribute DOMString version;
- readonly attribute DOMStringList objectStoreNames;
- IDBObjectStore createObjectStore (in DOMString name, in optional Object optionalParameters) raises (IDBDatabaseException);
- IDBRequest deleteObjectStore (in DOMString name) raises (IDBDatabaseException);
- IDBVersionChangeRequest setVersion ([TreatNullAs=EmptyString] in DOMString version);
- IDBTransaction transaction (in any storeNames, in optional unsigned short mode) raises (IDBDatabaseException);
- void close ();
- attribute Function onabort;
- attribute Function onerror;
- attribute Function onversionchange;
- };
- interface IDBRequest : EventTarget {
- readonly attribute any result get raises (IDBDatabaseException);
- readonly attribute unsigned short errorCode get raises (IDBDatabaseException);
- readonly attribute Object source;
- readonly attribute IDBTransaction transaction;
- const unsigned short LOADING = 1;
- const unsigned short DONE = 2;
- readonly attribute unsigned short readyState;
- attribute Function onsuccess;
- attribute Function onerror;
- };
重要:IndexedDB中,几乎所有的操作都是采用了command->request->result的方式。比如查询一条记录,返回一个request,在request的result中得到查询结果。又比如打开数据库,返回一个request,在request的result中得到返回的数据库引用。
从IDBFactory的方法体定义中可以看到,返回了一个IDBRequest对象。这个IDBRequest就是刚才所说的request。
下面给出一个通用的得到IDBDataBase的方法
- if (!window.indexedDB) {
- window.indexedDB = window.mozIndexedDB || window.webkitIndexedDB;
- }
- var request = indexedDB.open("MyTestDatabase");
- request.onsuccess = function(e) {
- // Obtain IDBDatabase
- // VERSION_CHANGE transaction callback
- var db = request.result;
- }
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接口的定义:
- interface IDBObjectStore {
- readonly attribute DOMString name;
- readonly attribute DOMString keyPath;
- readonly attribute DOMStringList indexNames;
- readonly attribute IDBTransaction transaction;
- IDBRequest put (in any value, in optional any key) raises (IDBDatabaseException, DOMException);
- IDBRequest add (in any value, in optional any key) raises (IDBDatabaseException, DOMException);
- IDBRequest delete (in any key) raises (IDBDatabaseException);
- IDBRequest get (in any key) raises (IDBDatabaseException);
- IDBRequest clear () raises (IDBDatabaseException);
- IDBRequest openCursor (in optional any range, in optional unsigned short direction) raises (IDBDatabaseException);
- IDBIndex createIndex (in DOMString name, in DOMString keyPath, in optional Object optionalParameters) raises (IDBDatabaseException);
- IDBIndex index (in DOMString name) raises (IDBDatabaseException);
- void deleteIndex (in DOMString indexName) raises (IDBDatabaseException);
- };
大家可以看到IDBDatabase中有一个createObjectStore方法。但是取得IDBDatabase后直接调用会报Exception。原因在于createObjectStore不能在version_change 的transaction callback中被调用。
下面给出通用的创建object store的代码
- var db = null;
- var customerData = [
- {ssn: "444-44-4444", name: "Bill", age: 25, email: "bill@company.com", nickName: ["1", "2", "3"]},
- {ssn: "555-55-5555", name: "Donna", age: 34, email: "donna@home.org"},
- {ssn: "666-66-6666", name: "Jack", age: 14, email: "jack@sina.com.cn"}
- ];
- request.onsuccess = function(e) {
- // Obtain IDBDatabase
- // VERSION_CHANGE transaction callback
- db = request.result;
- if (db.version != "1.0") {
- var requestVersion = db.setVersion("1.0");
- requestVersion.onerror = function(event) {
- alert(event);
- }
- requestVersion.onsuccess = function(event) {
- createObjectStore(db);
- }
- }
- db.close();
- };
- function createObjectStore(db) {
- if (db.objectStoreNames.contains('customers')) {
- db.deleteObjectStore("customers")
- }
- // Create Object Store
- // This method was not called from a VERSION_CHANGE transaction callback.
- var objectStore = db.createObjectStore("customers", {
- // primary key
- keyPath: "ssn",
- // auto increment
- autoIncrement: false
- });
- objectStore.createIndex("name", "name", { unique: false });
- objectStore.createIndex("email", "email", { unique: true });
- // Add initial data
- for (var index = 0; index < customerData.length; index++) {
- objectStore.add(customerData[index]);
- }
- }
以上代码创建了一个名为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
下面给出得到事务对象的通用方法
- // 通过IDBDatabase得到IDBTransaction
- var transaction = db.transaction(["customers"]);
- // 通过IDBTransaction得到IDBObjectStore
- var objectStore = transaction.objectStore("customers");
- // 打开游标,遍历customers中所有数据
- objectStore.openCursor().onsuccess = function(event) {
- var cursor = event.target.result;
- if (cursor) {
- var key = cursor.key;
- var rowData = cursor.value;
- alert(rowData.name);
- cursor.continue();
- }
- }
上面代码中使用了游标,这里要注意,在调用了cursor.continue之后,cursor会重新调用onsuccess句柄上的方法。所以,以上代码的onsuccess实际上被调用了3遍。至于openCursor的使用方法,下个Section中会有提到
Section 4:索引查询
section3中的objectStore.openCursor是根据keyPath去查询的。如果想通过某个索引去查询,可以用objectStore.index(索引名).openCursor去查询
1)openCursor的第一个参数为查询条件,他需要传入一个IDBKeyRange对象。
IDBKeyRange的创建方式有4种,都是调用了IDBKeyRange的静态方法。分别代表了4种不同类型的条件。
- // 只取得当前索引的值为Bill的数据
- IDBKeyRange.only("Bill");
- // 只取得当前索引的值大于Bill,并且不包括Bill的数据
- IDBKeyRange.lowerBound("Bill", true);
- // 只取得当前索引的值小于Bill,并且包括Bill的数据
- IDBKeyRange.upperBound("Bill", false);
- // 取得当前索引的值介于Bill和Jack之间,并且包括Bill,但不包括Jack的数据
- IDBKeyRange.bound("Bill", "Jack", false, true);
2)openCursor的第二个参数为游标方向。有4种
IDBCursor.NEXT 顺序循环
IDBCursor.NEXT_NO_DUPLICATE 顺序循环不重复
IDBCursor.PREV 倒序循环
IDBCursor.PREV_NO_DUPLICATE 倒序循环不重复
例子:
- var boundKeyRange = IDBKeyRange.upperBound("Jack", false);
- objectStore.index("name").openCursor(boundKeyRange, IDBCursor.PREV_NO_DUPLICATE).onsuccess = function(event) {
- var cursor = event.target.result;
- if (!cursor) {
- return;
- }
- var rowData = cursor.value;
- alert(rowData.name);
- cursor.continue();
- };
完整实例请参考附件。注意,indexedDB必须要在发布环境(web容器)中才可以运行。
- indexedDB.zip (2.6 KB)
HTML5之IndexedDB使用详解的更多相关文章
- 免费的HTML5连载来了《HTML5网页开发实例详解》连载(二)
最近新浪.百度.腾讯.京东.大众点评.淘宝等流行的网站都加大了招聘HTML5的力度,HTML5开发人员成了抢手货,本次连载的是由大众点评前端工程师和一淘网前端工程师基情奉献的<HTML5网页开发 ...
- 免费的HTML5连载来了《HTML5网页开发实例详解》连载(六)媒体查询
响应式设计的另一个重要技术手段是媒体查询.如果只是简单的设计一个流式布局系统,那么可以保证每个网格按比例的放大和缩小,但有可能会使得在小屏幕下(如手机设备)网格太小而严重影响阅读,这样的设计称不上响应 ...
- 免费的HTML5连载来了《HTML5网页开发实例详解》连载(五)图解通过Fiddler加速开发
Fiddler是Windows底下最强大的请求代理调试工具,监控任何浏览器的HTTP/HTTPS流量,窜改客户端请求和服务器响应,解密HTTPS Web会话,图4.44为Fiddler原理示意图. 图 ...
- 《HTML5网页开发实例详解》连载(四)HTML5中的FileSystem接口
HTML 5除了提供用于获取文件信息的File对象外,还添加了FileSystem相关的应用接口.FileSystem对于不同的处理功能做了细致的分类,如用于文件读取和处理的FileReader和Fi ...
- 免费的HTML5连载来了《HTML5网页开发实例详解》连载(三)DOCTYPE和字符集
在2.1.2节中通过新老DOCTYPE的对比,读者可以清晰地看到HTML 5在精简旧有结构上做出的努力.DOCTYPE在出现之初主要用于XML中,用作描述XML允许使用的元素.属性和排列方式.起初HT ...
- 当里个当,免费的HTML5连载来了《HTML5网页开发实例详解》连载(一)
读懂<HTML5网页开发实例详解>这本书 你还在用Flash嘛?帮主早不用了 乔布斯生前在公开信“Flash之我见”中预言:像HTML 5这样在移动时代中创立的新标准,将会在移动设备上获得 ...
- html5中output元素详解
html5中output元素详解 一.总结 一句话总结: output元素是HTML5新增的元素,用来设置不同数据的输出,没什么大用,了解即可 <form action="L3_01. ...
- html5的datalist元素详解
html5的datalist元素详解 一.总结 一句话总结: datalist元素配合input元素可以出现有提示选择作用的选框效果,还是相对比较简便好用的 1.optgroup元素是干嘛的? opt ...
- html5中section元素详解
html5中section元素详解 一.总结 一句话总结: section元素 用来定义文章中的章节(通常应该有标题和段落内容) section元素的作用就是给内容分段,给页面分区 1.section ...
随机推荐
- JMeter ----内置函数列表
Jmeter有两种类型的函数: 用户定义的静态值(或变量) 内置函数 用户定义的静态值允许用户定义变量时被替换为静态的值测试树编译并提交运行.需要注意的是,变量目前无法嵌套,即${Var${N}}不起 ...
- 摘:分配和释放BSTR的内存
当您创建 BSTR的并将它们使用以避免内存泄漏的它们在COM对象之间时,必须注意在将内存的. 当 BSTR 在接口中保持,必须释放其内存,当处理它. 但是,那么,当 BSTR ...
- 一个进程发起多个连接和gethostbyname等函数
一.在前面讲过的最简单的回射客户/服务器程序中,一个客户端即一个进程,只会发起一个连接,只要稍微修改一下就可以让一个客户端发起多个连 接,然后只利用其中一个连接发送数据. 先来认识一个函数getsoc ...
- 具体解释java中的volatilekeyword
一.为什么要有volatilekeyword 预计非常多java刚開始学习的人都被volatile这个keyword迷惑过.尽管网上有非常多讨论volatile的文章,但它们有的过于讲述底层原理,而没 ...
- JS高级心法——作用域链
首先我们来看两个js中的代码: <script type="text/javascript"> var c=5; function t1(){ var d=6 f ...
- react dva 的 connect 与 @connect
https://dvajs.com/guide/introduce-class.html#connect-方法 connect的作用是将组件和models结合在一起.将models中的state绑定到 ...
- JavaScript - 返回头部
制作浮动top $(window).scroll( function() { var scrollValue=$(window).scrollTop(); scrollValue > 600 ? ...
- spring mvc 依赖包
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop&l ...
- linux权限详解
一个用户.一个组 我们来看一看 Linux 权限和所有权模型.我们已经看到每个文件属于一个用户和一个组.这正是 Linux 中权限模型的核心.您可以在 ls -l 清单中查看用户和组: $ ls -l ...
- ASP.NET MVC 操作AD 获取域服务器当前用户姓名和OU信息
#region 根据当前登录域账号 获取AD用户姓名和所在OU目录 /// <summary> /// 根据当前登录域账号 获取AD用户姓名和所在OU目录 /// </summary ...