数据存储

Cordova 应用可以使用几种存储 API。有关更完整的概述和示例,请参阅 html5rocks 存储概述教程

每个 API 都有其优点和缺点,这里进行了总结。您应该选择最适合您需求的 API。您也可以在单个应用程序中为不同的目的使用几种不同的方法。

LocalStorage

本地存储提供简单的同步键/值对存储,并且所有 Cordova 平台上的底层 WebView 实现都支持本地存储。

使用总结

可以通过 window.localStorage 访问本地存储。以下代码片段显示了返回的 Storage 对象公开的最重要的方法

var storage = window.localStorage;
var value = storage.getItem(key); // Pass a key name to get its value.
storage.setItem(key, value) // Pass a key name and its value to add or update that key.
storage.removeItem(key) // Pass a key name to remove that key from storage.

有关更多信息,请参阅

优点

  • 所有 Cordova 平台都支持。
  • 它简单的同步 API 意味着它易于使用。

缺点

  • 仅存储字符串,因此复杂的数据结构必须序列化,并且只能存储可以序列化的数据。
  • 处理大量数据时性能较差。特别是
    • 缺少索引意味着搜索需要手动迭代所有数据。
    • 由于需要序列化/反序列化,存储大型或复杂的项目很慢。
    • 同步 API 意味着调用会锁定用户界面。
  • 总存储量有限(通常约为 5MB)。
  • 当需要空间时,iOS 将 localStorage 数据存储在可能被操作系统清除的位置。

IndexedDB

IndexedDB API 的目标是将 LocalStorage 和 WebSQL API 的优势结合起来,同时避免它们的缺点。IndexedDB 允许您存储任意 JavaScript 对象(前提是它们受结构化克隆算法支持),并使用键进行索引。它提供了一些 SQL 表的优点,而没有限制结构或需要预先定义它。

IndexedDB 提供了一个简单易懂的数据模型,很像 LocalStorage。但是,与 LocalStorage 不同,您可以创建多个数据库,每个数据库有多个存储,并且其异步 API 和搜索索引提供了性能优势。

所有平台上的底层 WebView 都支持 IndexedDB,但在 browser 平台上存在已知限制。

Web 浏览器限制

实际行为可能取决于使用的浏览器。例如,Safari 和 Firefox 浏览器上的行为可能存在差异。

使用总结

  • IndexedDB 异步工作 - 您请求一个特定的数据库操作,然后通过 DOM 事件获得结果通知。
  • 当您发出请求时,您会获得一个请求对象,该对象提供 onerroronsuccess 事件,以及 resulterrorreadyState 等属性。

以下代码片段演示了 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) {
    // Database is open and initialized - we're good to proceed.
    db = openRequest.result;
    displayData();
};
openRequest.onupgradeneeded = function (event) {
    // This is either a newly created database, or a new version number
    // has been submitted to the open() call.
    var db = event.target.result;
    db.onerror = function () {
        console.log(db.errorCode);
    };

    // Create an object store and indexes. A key is a data value used to organize
    // and retrieve values in the object store. The keyPath option identifies where
    // the key is stored. If a key path is specified, the store can only contain
    // JavaScript objects, and each object stored must have a property with the
    // same name as the key path (unless the autoIncrement option is true).
    var store = db.createObjectStore('customers', { keyPath: 'customerId' });

    // Define the indexes we want to use. Objects we add to the store don't need
    // to contain these properties, but they will only appear in the specified
    // index of they do.
    //
    // syntax: 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 });

    // Once the store is created, populate it
    store.transaction.oncomplete = function (event) {
        // The transaction method takes an array of the names of object stores
        // and indexes that will be in the scope of the transaction (or a single
        // string to access a single object store). The transaction will be
        // read-only unless the optional 'readwrite' parameter is specified.
        // It returns a transaction object, which provides an objectStore method
        // to access one of the object stores that are in the scope of this
        //transaction.
        var customerStore = db.transaction('customers', 'readwrite').objectStore('customers');
        customers.forEach(function (customer) {
            customerStore.add(customer);
        });
    };
};

function displayData() {
}

有关更多信息,请参阅

优点

  • 良好的性能 - 异步 API 不会阻塞 UI,索引提供了良好的搜索性能。
  • 简单的数据模型比 SQL 更容易学习。
  • 比 WebSQL 更灵活的结构。
  • 多个数据库和对象存储提供了比 LocalStorage 更多的结构。
  • 使用事务数据库模型带来稳健性。
  • 支持版本控制。

缺点

  • 带有嵌套回调的复杂 API。
  • 总存储量有限和可能的驱逐如 MDN 上所述

基于插件的选项

FileSystem API

FileSystem API 是一个由 Chrome 实现的 W3C 规范,但其他浏览器没有实现。它提供了在本地文件系统上存储和检索数据的 API,并且在 html5rocks 文章 中进行了详细描述。虽然任何 Cordova 平台都不原生支持该 API,但 File 插件 提供了在所有 Cordova 平台上都可用的广泛实现。

SQLite 插件

SQLite 插件提供了一个与上面描述的 WebSQL 几乎相同的 API。主要区别在于

  • 它在 Windows 平台上可用。
  • 它实际上没有大小限制。

它有以下几种变体

  • cordova-sqlite-storage - 包含其自己的 sqlite3 实现的核心版本。它支持 iOS、Android 和 Windows 平台。
  • cordova-sqlite-ext - 具有其他功能的扩展版本,包括 Android 和 iOS 上的 REGEXP 支持。
  • cordova-sqlite-evfree - 与 cordova-sqlite-ext 类似,但改进了内存处理。在 GPL v3 或商业许可下可用。

其他插件

搜索 Cordova 插件 以查找提供其他存储选项的其他插件。