[WebSimpleDB]HTML5之IndexedDB使用详解

摘要:
随着firefox4正式版的推出,IndexedDB正式进入我们的视线。IndexedDB是HTML5-WebStorage的重要一环,是一种轻量级NOSQL数据库。相较之下,WebDataBase标准已经很长时间没有更新,大有被IndexedDB取代的意思。Section1:起步,得到Database引用w3c为IndexedDB定义了很多接口,其中Database对象被定义为IDBDataBase。浏览器对象中,实现了IDBFactory的只有indexedDB这个实例。大家可以先看下IDBFactory和IDBDataBase接口的定义Js代码interfaceIDBFactory{IDBRequestopen;IDBRequestdeleteDatabase;};interfaceIDBDatabase:EventTarget{readonlyattributeDOMStringname;readonlyattributeDOMStringversion;readonlyattributeDOMStringListobjectStoreNames;IDBObjectStorecreateObjectStoreraises;IDBRequestdeleteObjectStoreraises;IDBVersionChangeRequestsetVersion;IDBTransactiontransactionraises;voidclose();attributeFunctiononabort;attributeFunctiononerror;attributeFunctiononversionchange;};interfaceIDBRequest:EventTarget{readonlyattributeanyresultgetraises;readonlyattributeunsignedshorterrorCodegetraises;readonlyattributeObjectsource;readonlyattributeIDBTransactiontransaction;constunsignedshortLOADING=1;constunsignedshortDONE=2;readonlyattributeunsignedshortreadyState;attributeFunctiononsuccess;attributeFunctiononerror;};重要:IndexedDB中,几乎所有的操作都是采用了command-˃request-˃result的方式。Section2:初始化objectstoreindexedDB标准建议,在初始化的时候创建表。而表在indexedDB中被称为objectstore。

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

Section 1:起步,得到Database引用

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

大家可以先看下IDBFactory和IDBDataBase接口的定义
Js代码
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的方法
Js代码
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接口的定义:
Js代码
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的代码
Js代码
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

下面给出得到事务对象的通用方法
Js代码
// 通过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种不同类型的条件。
Js代码
// 只取得当前索引的值为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 倒序循环不重复

例子:
Java代码
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容器)中才可以运行。

免责声明:文章转载自《[WebSimpleDB]HTML5之IndexedDB使用详解》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇利用C#线程窗口调试多线程程序手写签名提取工具(图片)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

HTML5学习

HTML5学习 1.HTML5 - 新特性 HTML5 中的一些有趣的新特性: 用于绘画的 canvas 元素 用于媒介回放的 video 和 audio 元素 对本地离线存储的更好的支持 新的特殊内容元素,比如 article、footer、header、nav、section 新的表单控件,比如 calendar、date、time、email、ur...

HTML5--(3)过渡+动画+颜色+文本

一.过渡transition transition-property指定属性名称(如width、height、background-color、内外边距)all 所有属性都将获得过渡效果(默认) attr 过渡效果的CSS属性名称列表,列表以逗号分隔 none 没有属性会获得过渡效果 transition-duration过渡时间3s (默认慢快...

12.手机端如何拖动组件--从零起步实现基于Html5的WEB设计器Jquery插件(含源码)

 前面示例都只是展示在桌面浏览器显示,当用手机浏览器打开时发现无法拖动元素,虽然实际业务上,手机也只是用来查看的,但为了论证手机上的触摸事件,我还是在本节做个演示。 手机上触控有三个重要事件touchstart,touchmove,touchend,分别表示开始触摸,移动,及结束,与鼠标的mousedown,mousemove,mouseup对应。 基于...

分享一个利用HTML5制作的海浪效果代码

在前面简单讲述了一下HTML里的Canvas,这次根据Canvas完成了“海浪效果”(水波上升)。 (O(∩_∩)O哈哈哈~作者我能看这个动画看一下午) 上升水波.gif 动画分析构成:贝塞尔曲线画布:Canvas效果:波浪涨潮(上升、波动)触发条件:点击按钮 贝塞尔曲线.gif 算法实现分析:从sin()函数切入,sin()越大波度起伏越大,简单说就...

谷歌浏览器 html5的声音和视频不能自动播放处理

AI模型开发就选MindSpore!新特性、新工具上线!>>> 声音无法自动播放这个在IOS/Android上面一直是个惯例,桌面版的Safari在2017年的11版本也宣布禁掉带有声音的多媒体自动播放功能,紧接着在2018年4月份发布的Chrome 66也正式关掉了声音自动播放,也就是说<audio autopaly><...

HTML5, CSS3, ES5新的web标准和浏览器支持一览 转

本文整理了一些最重要(或者说人气比较高罢)的新标准,虽然它们多数还只是w3c的草案,离Recommendation级别还早,却已经成为新一轮浏览器大战中备受追捧的明星,开发者社区里也涌现出大量相关的demo和API封装,有些已经进入生产环境(比如google在iphone上实现的gmail离线应用),其实我觉得如今的web领域里,从厂商私有技术转换成委员会...