存储

一些存储类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里删除这个键值对。

更多信息请查看:

优点

  • 所有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);
    });
});

更多信息请查看:

更多对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() {
}

更多信息请查看:

优点

  • 性能良好 - 异步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来获取其他插件,提供更多的存储方案。