存储(Storage)
一些存储类API对Cordova应用同样适用。完整的介绍和示例可以浏览html5rocks网站上的存储概览和使用指南。这里总结了每个API的优点和不足,你应该选择最适合自己需求的。当然你也可以在一个应用中针对不同的场景使用不同的API。
LocalStorage
LocalStorage提供了简单和同步的键值对存储方式,而且在各个Cordova平台,底层的WebView实现都支持它。
使用总结
LocalStorage可以通过window.localStorage访问到。以下的代码片段展示了返回的storage对象的最重要的几个方法。
var storage = window.localStorage;
var value = storage.getItem(key); // 传递键的名字获取对应的值。
storage.setItem(key, value) // 传递键的名字和对应的值去添加或者更新这个键值对。
storage.removeItem(key) // 传递键的名字去从LocalStorage里删除这个键值对。
更多信息请查看:
- W3C: webstorage
- MDN: Storage API
- MDN: Storage Guide
优点
- 所有Cordova平台支持.
- 它是简单并且同步的API,意味着使用很容易。
不足
- 只能存储字符串,所以复杂的数据结构必须被序列化才能存储。而且数据必须要能序列化,否则不能存储。
- 对大容量数据的支持很差,尤其在以下几个方面:
- 索引的欠缺意味着查询操作需要手动遍历所有数据。
- 存储复杂或者大量的数据会比较慢,因为要执行序列化和反序列化操作。
- 同步的API意味着API执行的时候会锁定用户界面。
- 存储容量有限制(一般为5MB)。
- 在IOS系统中,当空间不足的时候,系统可能会清空LocalStorage。
WebSQL
WebSQL提供了在结构化数据库中存储数据的API,这个数据库可以使用标准的SQL语法查询(实际上是SQLite)。同样的,WebSQL也提供了强大和复杂的SQL查询能力。
它只被以下Cordova平台的底层WebView实现支持:
- Android
- BlackBerry 10
- iOS
使用总结
创建或者打开一个数据库的切入点是使用window.openDatabase()方法:
var db = window.openDatabase(name, version, displayName, estimatedSize);
- name (string): 数据库的唯一名称,会被存在磁盘当中。
- version (string): 数据库的版本。
- displayName (string): 数据库的让人容易懂的名字,会被系统用来向用户描述这个数据库。
- estimatedSize (number): 数据库的预期最大容量,字节为单位。当数据库容量增长的时候,可能会提示用户获取授权。如果你设置了一个合理的容量,以后的提示就会比较少。
返回的Database对象提供了一个transaction()方法(或者readTransaction()方法初始化只读事务)来创建一个故障自动排除事务。
var db = window.openDatabase(name, version, displayName, estimatedSize);
db.transaction(function (tx) {
tx.executeSql(sqlStatement, valueArray, function (tx, result) {
console.log(result);
}, function (error) {
console.log(error);
});
});
更多信息请查看:
- W3C: WebSQL
- TutorialsPoint: WebSQL Guide
更多对SQL语言的介绍,请查看:
- w3schools: Introduction to SQL
使用数据库版本
当打开一个已存在的数据库,如果指定的版本和数据库的版本不匹配,数据库会报异常并且无法打开。但是,如果你指定的版本是一个空字符串,无论数据库当前是什么版本,它都会打开(你可以通过db.version查看当前版本)。然而,谨慎起见,当数据库创建的时候,它的版本会赋给一个空字符串。
优点
- 性能良好 - 数据可以索引从而提供快速查询,而且异步API意味着不会锁定用户界面。
- 事务型数据库模型的健壮性。
- 提供版本支持。
不足
- 不是所有Cordova平台都支持。
- 比LocalStorage和IndexedDB复杂。
- WebSQL API已弃用。它不太可能在目前不支持它的平台上获得支持,甚至有可能被移除。
- 需要预先定义严格的结构。
- 存储容量有限制(一般为5MB)。
IndexedDB
IndexedDB的目标是结合LocalStorage和WebSQL的优点并避免它们的缺点。IndexedDB允许你存储任意的JavaScript对象(由structured clone algorithm提供支持)并以一个键来索引。它不需要限制结构或者提前定义就能提供SQL表的一些好用的功能。
IndexedDB提供了一个简单的容易理解的数据模型,很像LocalStorage。但和LocalStorage不同的是,你可以创建多个数据库,一个数据库多条存储数据。并且异步的API和索引支持提供了更好的性能表现。
IndexedDB被以下Cordova平台的底层WebView实现支持:
- BlackBerry 10
- Windows (with some limitations)
- Android (4.4 and above)
Windows的限制
Windows平台对IndexedDB的支持不完整。例如,它缺少以下的特性:
- 在web workers里面不可用。
- 不支持数组keyPaths。
- 不支持数组Key。
- 混合索引不支持对象查找。
使用总结
- IndexedDB是异步的 - 你请求一个特定的数据库操作,然后通过一个DOM事件接收到响应。
- 当你发起一个请求,你会得到一个请求对象。这个对象提供onerror和onsuccess事件,和result、error、readyState等属性类似。
下面的代码片段展示了一些IndexedDB的简单用法:
var db;
var databaseName = 'myDB';
var databaseVersion = 1;
var openRequest = window.indexedDB.open(databaseName, databaseVersion);
openRequest.onerror = function (event) {
console.log(openRequest.errorCode);
};
openRequest.onsuccess = function (event) {
// 数据库已经打开并初始化 - 我们进行的不错,可以继续了.
db = openRequest.result;
displayData();
};
openRequest.onupgradeneeded = function (event) {
// 一个新的数据库,或者一个新的版本号被传递给open方法调用。
var db = event.target.result;
db.onerror = function () {
console.log(db.errorCode);
};
// 创建一个存储对象。key是用来标识这个存储对象。
//keyPath参数定义了key存储的地方。如果keyPath指定了,那么这个存储对象只能包含JavaScript对象,
//而且每个对象必须有一个属性名字和keyPath相同(除非autoIncrement选项是true)。
var store = db.createObjectStore('customers', { keyPath: 'customerId' });
// 定义我们想要使用的索引。我们创建的存储对象不需要包含这些属性,它们只会出现在指定的索引中。
//
// 使用方式: store.createIndex(indexName, keyPath[, parameters]);
//
// All these values could have duplicates, so set unique to false
store.createIndex('firstName', 'firstName', { unique: false });
store.createIndex('lastName', 'lastName', { unique: false });
store.createIndex('street', 'street', { unique: false });
store.createIndex('city', 'city', { unique: false });
store.createIndex('zipCode', 'zipCode', { unique: false });
store.createIndex('country', 'country', { unique: false });
// 一旦store创建成功,就可以存储数据了。
store.transaction.oncomplete = function (event) {
// transaction方法获取到存储对象名字和索引的数组(或者一个单字符串去得到一个单独的存储对象),它们都在事务的作用域里。
// 事务是只读的,除非指定了readwrite选项。
//它返回了一个对象,这个对象提供了objectStore方法去访问transaction作用域里的对象。
var customerStore = db.transaction('customers', 'readwrite').objectStore('customers');
customers.forEach(function (customer) {
customerStore.add(customer);
});
};
};
function displayData() {
}
更多信息请查看:
- W3C: IndexedDB
- MDN: IndexedDB API Reference
- MDN: IndexedDB Basic Concepts
- MDN: Using IndexedDB Guide
优点
- 性能良好 - 异步API不会锁定用户界面,而且索引功能提供了良好的搜索性能。
- 数据模型简单,比SQL还容易学习。
- 比WebSQL更弹性的数据结构。
- 多数据和多对象存储提供了比LocalStorage更丰富的数据结构。
- 事务型数据库模型的健壮性。
- 提供版本支持。
不足
- IOS平台不支持。
- 带嵌套回调,API复杂。
- 存储容量有限制(一般为5MB)。
插件说明
FileSystem API
FileSystem API是W3C规范。Chrome浏览器实现了它,其他浏览器还没有。它通过本地的文件系统,提供API存储和获取数据,html5rocks article上有对它的细节很好的介绍。然而这些API在所有Cordova平台上都没有原生的支持,但是File plugin提供了跨所有Cordova平台的广泛的实现。
SQLite 插件
SQLite插件提供的API几乎和上面介绍的WebSQL一样。它的主要不同是:
- 它在Windows平台上可用。
- 它没用存储容量限制。
它在下面的几个变种中也是可用的:
- cordova-sqlite-storage - 包含sqlite3实现的核心版本,它支持iOS, Android和Windows平台。
- cordova-sqlite-ext - 包含Android和iOS的正则支持等额外特性的扩展版本。
- cordova-sqlite-evfree - 与cordova-sqlite-ext类似,但提供了高级的内存管理。GPL版本低于v3或者有商业许可的话可用。
其他插件
搜索Cordova plugins来获取其他插件,提供更多的存储方案。