<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # IndexedDB API ## 概述 隨著瀏覽器的功能不斷增強,越來越多的網站開始考慮,將大量數據儲存在客戶端,這樣可以減少從服務器獲取數據,直接從本地獲取數據。 現有的瀏覽器數據儲存方案,都不適合儲存大量數據:Cookie 的大小不超過 4KB,且每次請求都會發送回服務器;LocalStorage 在 2.5MB 到 10MB 之間(各家瀏覽器不同),而且不提供搜索功能,不能建立自定義的索引。所以,需要一種新的解決方案,這就是 IndexedDB 誕生的背景。 通俗地說,IndexedDB 就是瀏覽器提供的本地數據庫,它可以被網頁腳本創建和操作。IndexedDB 允許儲存大量數據,提供查找接口,還能建立索引。這些都是 LocalStorage 所不具備的。就數據庫類型而言,IndexedDB 不屬于關系型數據庫(不支持 SQL 查詢語句),更接近 NoSQL 數據庫。 IndexedDB 具有以下特點。 **(1)鍵值對儲存。** IndexedDB 內部采用對象倉庫(object store)存放數據。所有類型的數據都可以直接存入,包括 JavaScript 對象。對象倉庫中,數據以“鍵值對”的形式保存,每一個數據記錄都有對應的主鍵,主鍵是獨一無二的,不能有重復,否則會拋出一個錯誤。 **(2)異步。** IndexedDB 操作時不會鎖死瀏覽器,用戶依然可以進行其他操作,這與 LocalStorage 形成對比,后者的操作是同步的。異步設計是為了防止大量數據的讀寫,拖慢網頁的表現。 **(3)支持事務。** IndexedDB 支持事務(transaction),這意味著一系列操作步驟之中,只要有一步失敗,整個事務就都取消,數據庫回滾到事務發生之前的狀態,不存在只改寫一部分數據的情況。 **(4)同源限制。** IndexedDB 受到同源限制,每一個數據庫對應創建它的域名。網頁只能訪問自身域名下的數據庫,而不能訪問跨域的數據庫。 **(5)儲存空間大。** IndexedDB 的儲存空間比 LocalStorage 大得多,一般來說不少于 250MB,甚至沒有上限。 **(6)支持二進制儲存。** IndexedDB 不僅可以儲存字符串,還可以儲存二進制數據(ArrayBuffer 對象和 Blob 對象)。 ## 基本概念 IndexedDB 是一個比較復雜的 API,涉及不少概念。它把不同的實體,抽象成一個個對象接口。學習這個 API,就是學習它的各種對象接口。 - 數據庫:IDBDatabase 對象 - 對象倉庫:IDBObjectStore 對象 - 索引: IDBIndex 對象 - 事務: IDBTransaction 對象 - 操作請求:IDBRequest 對象 - 指針: IDBCursor 對象 - 主鍵集合:IDBKeyRange 對象 下面是一些主要的概念。 **(1)數據庫** 數據庫是一系列相關數據的容器。每個域名(嚴格的說,是協議 + 域名 + 端口)都可以新建任意多個數據庫。 IndexedDB 數據庫有版本的概念。同一個時刻,只能有一個版本的數據庫存在。如果要修改數據庫結構(新增或刪除表、索引或者主鍵),只能通過升級數據庫版本完成。 **(2)對象倉庫** 每個數據庫包含若干個對象倉庫(object store)。它類似于關系型數據庫的表格。 **(3)數據記錄** 對象倉庫保存的是數據記錄。每條記錄類似于關系型數據庫的行,但是只有主鍵和數據體兩部分。主鍵用來建立默認的索引,必須是不同的,否則會報錯。主鍵可以是數據記錄里面的一個屬性,也可以指定為一個遞增的整數編號。 ```javascript { id: 1, text: 'foo' } ``` 上面的對象中,`id`屬性可以當作主鍵。 數據體可以是任意數據類型,不限于對象。 **(4)索引** 為了加速數據的檢索,可以在對象倉庫里面,為不同的屬性建立索引。 **(5)事務** 數據記錄的讀寫和刪改,都要通過事務完成。事務對象提供`error`、`abort`和`complete`三個事件,用來監聽操作結果。 ## 操作流程 IndexedDB 數據庫的各種操作,一般是按照下面的流程進行的。這個部分只給出簡單的代碼示例,用于快速上手,詳細的各個對象的 API 放在后文介紹。 ### 打開數據庫 使用 IndexedDB 的第一步是打開數據庫,使用`indexedDB.open()`方法。 ```javascript var request = window.indexedDB.open(databaseName, version); ``` 這個方法接受兩個參數,第一個參數是字符串,表示數據庫的名字。如果指定的數據庫不存在,就會新建數據庫。第二個參數是整數,表示數據庫的版本。如果省略,打開已有數據庫時,默認為當前版本;新建數據庫時,默認為`1`。 `indexedDB.open()`方法返回一個 IDBRequest 對象。這個對象通過三種事件`error`、`success`、`upgradeneeded`,處理打開數據庫的操作結果。 **(1)error 事件** `error`事件表示打開數據庫失敗。 ```javascript request.onerror = function (event) { console.log('數據庫打開報錯'); }; ``` **(2)success 事件** `success`事件表示成功打開數據庫。 ```javascript var db; request.onsuccess = function (event) { db = request.result; console.log('數據庫打開成功'); }; ``` 這時,通過`request`對象的`result`屬性拿到數據庫對象。 **(3)upgradeneeded 事件** 如果指定的版本號,大于數據庫的實際版本號,就會發生數據庫升級事件`upgradeneeded`。 ```javascript var db; request.onupgradeneeded = function (event) { db = event.target.result; } ``` 這時通過事件對象的`target.result`屬性,拿到數據庫實例。 ### 新建數據庫 新建數據庫與打開數據庫是同一個操作。如果指定的數據庫不存在,就會新建。不同之處在于,后續的操作主要在`upgradeneeded`事件的監聽函數里面完成,因為這時版本從無到有,所以會觸發這個事件。 通常,新建數據庫以后,第一件事是新建對象倉庫(即新建表)。 ```javascript request.onupgradeneeded = function(event) { db = event.target.result; var objectStore = db.createObjectStore('person', { keyPath: 'id' }); } ``` 上面代碼中,數據庫新建成功以后,新增一張叫做`person`的表格,主鍵是`id`。 更好的寫法是先判斷一下,這張表格是否存在,如果不存在再新建。 ```javascript request.onupgradeneeded = function (event) { db = event.target.result; var objectStore; if (!db.objectStoreNames.contains('person')) { objectStore = db.createObjectStore('person', { keyPath: 'id' }); } } ``` 主鍵(key)是默認建立索引的屬性。比如,數據記錄是`{ id: 1, name: '張三' }`,那么`id`屬性可以作為主鍵。主鍵也可以指定為下一層對象的屬性,比如`{ foo: { bar: 'baz' } }`的`foo.bar`也可以指定為主鍵。 如果數據記錄里面沒有合適作為主鍵的屬性,那么可以讓 IndexedDB 自動生成主鍵。 ```javascript var objectStore = db.createObjectStore( 'person', { autoIncrement: true } ); ``` 上面代碼中,指定主鍵為一個遞增的整數。 新建對象倉庫以后,下一步可以新建索引。 ```javascript request.onupgradeneeded = function(event) { db = event.target.result; var objectStore = db.createObjectStore('person', { keyPath: 'id' }); objectStore.createIndex('name', 'name', { unique: false }); objectStore.createIndex('email', 'email', { unique: true }); } ``` 上面代碼中,`IDBObject.createIndex()`的三個參數分別為索引名稱、索引所在的屬性、配置對象(說明該屬性是否包含重復的值)。 ### 新增數據 新增數據指的是向對象倉庫寫入數據記錄。這需要通過事務完成。 ```javascript function add() { var request = db.transaction(['person'], 'readwrite') .objectStore('person') .add({ id: 1, name: '張三', age: 24, email: 'zhangsan@example.com' }); request.onsuccess = function (event) { console.log('數據寫入成功'); }; request.onerror = function (event) { console.log('數據寫入失敗'); } } add(); ``` 上面代碼中,寫入數據需要新建一個事務。新建時必須指定表格名稱和操作模式(“只讀”或“讀寫”)。新建事務以后,通過`IDBTransaction.objectStore(name)`方法,拿到 IDBObjectStore 對象,再通過表格對象的`add()`方法,向表格寫入一條記錄。 寫入操作是一個異步操作,通過監聽連接對象的`success`事件和`error`事件,了解是否寫入成功。 ### 讀取數據 讀取數據也是通過事務完成。 ```javascript function read() { var transaction = db.transaction(['person']); var objectStore = transaction.objectStore('person'); var request = objectStore.get(1); request.onerror = function(event) { console.log('事務失敗'); }; request.onsuccess = function( event) { if (request.result) { console.log('Name: ' + request.result.name); console.log('Age: ' + request.result.age); console.log('Email: ' + request.result.email); } else { console.log('未獲得數據記錄'); } }; } read(); ``` 上面代碼中,`objectStore.get()`方法用于讀取數據,參數是主鍵的值。 ### 遍歷數據 遍歷數據表格的所有記錄,要使用指針對象 IDBCursor。 ```javascript function readAll() { var objectStore = db.transaction('person').objectStore('person'); objectStore.openCursor().onsuccess = function (event) { var cursor = event.target.result; if (cursor) { console.log('Id: ' + cursor.key); console.log('Name: ' + cursor.value.name); console.log('Age: ' + cursor.value.age); console.log('Email: ' + cursor.value.email); cursor.continue(); } else { console.log('沒有更多數據了!'); } }; } readAll(); ``` 上面代碼中,新建指針對象的`openCursor()`方法是一個異步操作,所以要監聽`success`事件。 ### 更新數據 更新數據要使用`IDBObject.put()`方法。 ```javascript function update() { var request = db.transaction(['person'], 'readwrite') .objectStore('person') .put({ id: 1, name: '李四', age: 35, email: 'lisi@example.com' }); request.onsuccess = function (event) { console.log('數據更新成功'); }; request.onerror = function (event) { console.log('數據更新失敗'); } } update(); ``` 上面代碼中,`put()`方法自動更新了主鍵為`1`的記錄。 ### 刪除數據 `IDBObjectStore.delete()`方法用于刪除記錄。 ```javascript function remove() { var request = db.transaction(['person'], 'readwrite') .objectStore('person') .delete(1); request.onsuccess = function (event) { console.log('數據刪除成功'); }; } remove(); ``` ### 使用索引 索引的意義在于,可以讓你搜索任意字段,也就是說從任意字段拿到數據記錄。如果不建立索引,默認只能搜索主鍵(即從主鍵取值)。 假定新建表格的時候,對`name`字段建立了索引。 ```javascript objectStore.createIndex('name', 'name', { unique: false }); ``` 現在,就可以從`name`找到對應的數據記錄了。 ```javascript var transaction = db.transaction(['person'], 'readonly'); var store = transaction.objectStore('person'); var index = store.index('name'); var request = index.get('李四'); request.onsuccess = function (e) { var result = e.target.result; if (result) { // ... } else { // ... } } ``` ## indexedDB 對象 瀏覽器原生提供`indexedDB`對象,作為開發者的操作接口。 ### indexedDB.open() `indexedDB.open()`方法用于打開數據庫。這是一個異步操作,但是會立刻返回一個 IDBOpenDBRequest 對象。 ```javascript var openRequest = window.indexedDB.open('test', 1); ``` 上面代碼表示,打開一個名為`test`、版本為`1`的數據庫。如果該數據庫不存在,則會新建該數據庫。 `open()`方法的第一個參數是數據庫名稱,格式為字符串,不可省略;第二個參數是數據庫版本,是一個大于`0`的正整數(`0`將報錯),如果該參數大于當前版本,會觸發數據庫升級。第二個參數可省略,如果數據庫已存在,將打開當前版本的數據庫;如果數據庫不存在,將創建該版本的數據庫,默認版本為`1`。 打開數據庫是異步操作,通過各種事件通知客戶端。下面是有可能觸發的4種事件。 - **success**:打開成功。 - **error**:打開失敗。 - **upgradeneeded**:第一次打開該數據庫,或者數據庫版本發生變化。 - **blocked**:上一次的數據庫連接還未關閉。 第一次打開數據庫時,會先觸發`upgradeneeded`事件,然后觸發`success`事件。 根據不同的需要,對上面4種事件監聽函數。 ```javascript var openRequest = indexedDB.open('test', 1); var db; openRequest.onupgradeneeded = function (e) { console.log('Upgrading...'); } openRequest.onsuccess = function (e) { console.log('Success!'); db = openRequest.result; } openRequest.onerror = function (e) { console.log('Error'); console.log(e); } ``` 上面代碼有兩個地方需要注意。首先,`open()`方法返回的是一個對象(IDBOpenDBRequest),監聽函數就定義在這個對象上面。其次,`success`事件發生后,從`openRequest.result`屬性可以拿到已經打開的`IndexedDB`數據庫對象。 ### indexedDB.deleteDatabase() `indexedDB.deleteDatabase()`方法用于刪除一個數據庫,參數為數據庫的名字。它會立刻返回一個`IDBOpenDBRequest`對象,然后對數據庫執行異步刪除。刪除操作的結果會通過事件通知,`IDBOpenDBRequest`對象可以監聽以下事件。 - `success`:刪除成功 - `error`:刪除報錯 ```javascript var DBDeleteRequest = window.indexedDB.deleteDatabase('demo'); DBDeleteRequest.onerror = function (event) { console.log('Error'); }; DBDeleteRequest.onsuccess = function (event) { console.log('success'); }; ``` 調用`deleteDatabase()`方法以后,當前數據庫的其他已經打開的連接都會接收到`versionchange`事件。 注意,刪除不存在的數據庫并不會報錯。 ### indexedDB.cmp() `indexedDB.cmp()`方法比較兩個值是否為 indexedDB 的相同的主鍵。它返回一個整數,表示比較的結果:`0`表示相同,`1`表示第一個主鍵大于第二個主鍵,`-1`表示第一個主鍵小于第二個主鍵。 ```javascript window.indexedDB.cmp(1, 2) // -1 ``` 注意,這個方法不能用來比較任意的 JavaScript 值。如果參數是布爾值或對象,它會報錯。 ```javascript window.indexedDB.cmp(1, true) // 報錯 window.indexedDB.cmp({}, {}) // 報錯 ``` ## IDBRequest 對象 IDBRequest 對象表示打開的數據庫連接,`indexedDB.open()`方法和`indexedDB.deleteDatabase()`方法會返回這個對象。數據庫的操作都是通過這個對象完成的。 這個對象的所有操作都是異步操作,要通過`readyState`屬性判斷是否完成,如果為`pending`就表示操作正在進行,如果為`done`就表示操作完成,可能成功也可能失敗。 操作完成以后,觸發`success`事件或`error`事件,這時可以通過`result`屬性和`error`屬性拿到操作結果。如果在`pending`階段,就去讀取這兩個屬性,是會報錯的。 IDBRequest 對象有以下屬性。 - `IDBRequest.readyState`:等于`pending`表示操作正在進行,等于`done`表示操作正在完成。 - `IDBRequest.result`:返回請求的結果。如果請求失敗、結果不可用,讀取該屬性會報錯。 - `IDBRequest.error`:請求失敗時,返回錯誤對象。 - `IDBRequest.source`:返回請求的來源(比如索引對象或 ObjectStore)。 - `IDBRequest.transaction`:返回當前請求正在進行的事務,如果不包含事務,返回`null`。 - `IDBRequest.onsuccess`:指定`success`事件的監聽函數。 - `IDBRequest.onerror`:指定`error`事件的監聽函數。 IDBOpenDBRequest 對象繼承了 IDBRequest 對象,提供了兩個額外的事件監聽屬性。 - `IDBOpenDBRequest.onblocked`:指定`blocked`事件(`upgradeneeded`事件觸發時,數據庫仍然在使用)的監聽函數。 - `IDBOpenDBRequest.onupgradeneeded`:`upgradeneeded`事件的監聽函數。 ## IDBDatabase 對象 打開數據成功以后,可以從`IDBOpenDBRequest`對象的`result`屬性上面,拿到一個`IDBDatabase`對象,它表示連接的數據庫。后面對數據庫的操作,都通過這個對象完成。 ```javascript var db; var DBOpenRequest = window.indexedDB.open('demo', 1); DBOpenRequest.onerror = function (event) { console.log('Error'); }; DBOpenRequest.onsuccess = function(event) { db = DBOpenRequest.result; // ... }; ``` ### 屬性 IDBDatabase 對象有以下屬性。 - `IDBDatabase.name`:字符串,數據庫名稱。 - `IDBDatabase.version`:整數,數據庫版本。數據庫第一次創建時,該屬性為空字符串。 - `IDBDatabase.objectStoreNames`:DOMStringList 對象(字符串的集合),包含當前數據的所有 object store 的名字。 - `IDBDatabase.onabort`:指定 abort 事件(事務中止)的監聽函數。 - `IDBDatabase.onclose`:指定 close 事件(數據庫意外關閉)的監聽函數。 - `IDBDatabase.onerror`:指定 error 事件(訪問數據庫失敗)的監聽函數。 - `IDBDatabase.onversionchange`:數據庫版本變化時觸發(發生`upgradeneeded`事件,或調用`indexedDB.deleteDatabase()`)。 下面是`objectStoreNames`屬性的例子。該屬性返回一個 DOMStringList 對象,包含了當前數據庫所有對象倉庫的名稱(即表名),可以使用 DOMStringList 對象的`contains`方法,檢查數據庫是否包含某個對象倉庫。 ```javascript if (!db.objectStoreNames.contains('firstOS')) { db.createObjectStore('firstOS'); } ``` 上面代碼先判斷某個對象倉庫是否存在,如果不存在就創建該對象倉庫。 ### 方法 IDBDatabase 對象有以下方法。 - `IDBDatabase.close()`:關閉數據庫連接,實際會等所有事務完成后再關閉。 - `IDBDatabase.createObjectStore()`:創建存放數據的對象倉庫,類似于傳統關系型數據庫的表格,返回一個 IDBObjectStore 對象。該方法只能在`versionchange`事件監聽函數中調用。 - `IDBDatabase.deleteObjectStore()`:刪除指定的對象倉庫。該方法只能在`versionchange`事件監聽函數中調用。 - `IDBDatabase.transaction()`:返回一個 IDBTransaction 事務對象。 下面是`createObjectStore()`方法的例子。 ```javascript var request = window.indexedDB.open('demo', 2); request.onupgradeneeded = function (event) { var db = event.target.result; db.onerror = function(event) { console.log('error'); }; var objectStore = db.createObjectStore('items'); // ... }; ``` 上面代碼創建了一個名為`items`的對象倉庫,如果該對象倉庫已經存在,就會拋出一個錯誤。為了避免出錯,需要用到下文的`objectStoreNames`屬性,檢查已有哪些對象倉庫。 `createObjectStore()`方法還可以接受第二個對象參數,用來設置對象倉庫的屬性。 ```javascript db.createObjectStore('test', { keyPath: 'email' }); db.createObjectStore('test2', { autoIncrement: true }); ``` 上面代碼中,`keyPath`屬性表示主鍵(由于主鍵的值不能重復,所以上例存入之前,必須保證數據的`email`屬性值都是不一樣的),默認值為`null`;`autoIncrement`屬性表示,是否使用自動遞增的整數作為主鍵(第一個數據記錄為1,第二個數據記錄為2,以此類推),默認為`false`。一般來說,`keyPath`和`autoIncrement`屬性只要使用一個就夠了,如果兩個同時使用,表示主鍵為遞增的整數,且對象不得缺少`keyPath`指定的屬性。 下面是`deleteObjectStore()`方法的例子。 ```javascript var dbName = 'sampleDB'; var dbVersion = 2; var request = indexedDB.open(dbName, dbVersion); request.onupgradeneeded = function(e) { var db = request.result; if (e.oldVersion < 1) { db.createObjectStore('store1'); } if (e.oldVersion < 2) { db.deleteObjectStore('store1'); db.createObjectStore('store2'); } // ... }; ``` 下面是`transaction()`方法的例子,該方法用于創建一個數據庫事務,返回一個 IDBTransaction 對象。向數據庫添加數據之前,必須先創建數據庫事務。 ```javascript var t = db.transaction(['items'], 'readwrite'); ``` `transaction()`方法接受兩個參數:第一個參數是一個數組,里面是所涉及的對象倉庫,通常是只有一個;第二個參數是一個表示操作類型的字符串。目前,操作類型只有兩種:`readonly`(只讀)和`readwrite`(讀寫)。添加數據使用`readwrite`,讀取數據使用`readonly`。第二個參數是可選的,省略時默認為`readonly`模式。 ## IDBObjectStore 對象 IDBObjectStore 對象對應一個對象倉庫(object store)。`IDBDatabase.createObjectStore()`方法返回的就是一個 IDBObjectStore 對象。 IDBDatabase 對象的`transaction()`返回一個事務對象,該對象的`objectStore()`方法返回 IDBObjectStore 對象,因此可以采用下面的鏈式寫法。 ```javascript db.transaction(['test'], 'readonly') .objectStore('test') .get(X) .onsuccess = function (e) {} ``` ### 屬性 IDBObjectStore 對象有以下屬性。 - `IDBObjectStore.indexNames`:返回一個類似數組的對象(DOMStringList),包含了當前對象倉庫的所有索引。 - `IDBObjectStore.keyPath`:返回當前對象倉庫的主鍵。 - `IDBObjectStore.name`:返回當前對象倉庫的名稱。 - `IDBObjectStore.transaction`:返回當前對象倉庫所屬的事務對象。 - `IDBObjectStore.autoIncrement`:布爾值,表示主鍵是否會自動遞增。 ### 方法 IDBObjectStore 對象有以下方法。 **(1)IDBObjectStore.add()** `IDBObjectStore.add()`用于向對象倉庫添加數據,返回一個 IDBRequest 對象。該方法只用于添加數據,如果主鍵相同會報錯,因此更新數據必須使用`put()`方法。 ```javascript objectStore.add(value, key) ``` 該方法接受兩個參數,第一個參數是鍵值,第二個參數是主鍵,該參數可選,如果省略默認為`null`。 創建事務以后,就可以獲取對象倉庫,然后使用`add()`方法往里面添加數據了。 ```javascript var db; var DBOpenRequest = window.indexedDB.open('demo', 1); DBOpenRequest.onsuccess = function (event) { db = DBOpenRequest.result; var transaction = db.transaction(['items'], 'readwrite'); transaction.oncomplete = function (event) { console.log('transaction success'); }; transaction.onerror = function (event) { console.log('transaction error: ' + transaction.error); }; var objectStore = transaction.objectStore('items'); var objectStoreRequest = objectStore.add({ foo: 1 }); objectStoreRequest.onsuccess = function (event) { console.log('add data success'); }; }; ``` **(2)IDBObjectStore.put()** `IDBObjectStore.put()`方法用于更新某個主鍵對應的數據記錄,如果對應的鍵值不存在,則插入一條新的記錄。該方法返回一個 IDBRequest 對象。 ```javascript objectStore.put(item, key) ``` 該方法接受兩個參數,第一個參數為新數據,第二個參數為主鍵,該參數可選,且只在自動遞增時才有必要提供,因為那時主鍵不包含在數據值里面。 **(3)IDBObjectStore.clear()** `IDBObjectStore.clear()`刪除當前對象倉庫的所有記錄。該方法返回一個 IDBRequest 對象。 ```javascript objectStore.clear() ``` 該方法不需要參數。 **(4)IDBObjectStore.delete()** `IDBObjectStore.delete()`方法用于刪除指定主鍵的記錄。該方法返回一個 IDBRequest 對象。 ```javascript objectStore.delete(Key) ``` 該方法的參數為主鍵的值。 **(5)IDBObjectStore.count()** `IDBObjectStore.count()`方法用于計算記錄的數量。該方法返回一個 IDBRequest 對象。 ```javascript IDBObjectStore.count(key) ``` 不帶參數時,該方法返回當前對象倉庫的所有記錄數量。如果主鍵或 IDBKeyRange 對象作為參數,則返回對應的記錄數量。 **(6)IDBObjectStore.getKey()** `IDBObjectStore.getKey()`用于獲取主鍵。該方法返回一個 IDBRequest 對象。 ```javascript objectStore.getKey(key) ``` 該方法的參數可以是主鍵值或 IDBKeyRange 對象。 **(7)IDBObjectStore.get()** `IDBObjectStore.get()`用于獲取主鍵對應的數據記錄。該方法返回一個 IDBRequest 對象。 ```javascript objectStore.get(key) ``` **(8)IDBObjectStore.getAll()** `DBObjectStore.getAll()`用于獲取對象倉庫的記錄。該方法返回一個 IDBRequest 對象。 ```javascript // 獲取所有記錄 objectStore.getAll() // 獲取所有符合指定主鍵或 IDBKeyRange 的記錄 objectStore.getAll(query) // 指定獲取記錄的數量 objectStore.getAll(query, count) ``` **(9)IDBObjectStore.getAllKeys()** `IDBObjectStore.getAllKeys()`用于獲取所有符合條件的主鍵。該方法返回一個 IDBRequest 對象。 ```javascript // 獲取所有記錄的主鍵 objectStore.getAllKeys() // 獲取所有符合條件的主鍵 objectStore.getAllKeys(query) // 指定獲取主鍵的數量 objectStore.getAllKeys(query, count) ``` **(10)IDBObjectStore.index()** `IDBObjectStore.index()`方法返回指定名稱的索引對象 IDBIndex。 ```javascript objectStore.index(name) ``` 有了索引以后,就可以針對索引所在的屬性讀取數據。 ```javascript var t = db.transaction(['people'], 'readonly'); var store = t.objectStore('people'); var index = store.index('name'); var request = index.get('foo'); ``` 上面代碼打開對象倉庫以后,先用`index()`方法指定獲取`name`屬性的索引,然后用`get()`方法讀取某個`name`屬性(`foo`)對應的數據。如果`name`屬性不是對應唯一值,這時`get()`方法有可能取回多個數據對象。另外,`get()`是異步方法,讀取成功以后,只能在`success`事件的監聽函數中處理數據。 **(11)IDBObjectStore.createIndex()** `IDBObjectStore.createIndex()`方法用于新建當前數據庫的一個索引。該方法只能在`VersionChange`監聽函數里面調用。 ```javascript objectStore.createIndex(indexName, keyPath, objectParameters) ``` 該方法可以接受三個參數。 - indexName:索引名 - keyPath:主鍵 - objectParameters:配置對象(可選) 第三個參數可以配置以下屬性。 - unique:如果設為`true`,將不允許重復的值 - multiEntry:如果設為`true`,對于有多個值的主鍵數組,每個值將在索引里面新建一個條目,否則主鍵數組對應一個條目。 假定對象倉庫中的數據記錄都是如下的`person`類型。 ```javascript var person = { name: name, email: email, created: new Date() }; ``` 可以指定這個對象的某個屬性來建立索引。 ```javascript var store = db.createObjectStore('people', { autoIncrement: true }); store.createIndex('name', 'name', { unique: false }); store.createIndex('email', 'email', { unique: true }); ``` 上面代碼告訴索引對象,`name`屬性不是唯一值,`email`屬性是唯一值。 **(12)IDBObjectStore.deleteIndex()** `IDBObjectStore.deleteIndex()`方法用于刪除指定的索引。該方法只能在`VersionChange`監聽函數里面調用。 ```javascript objectStore.deleteIndex(indexName) ``` **(13)IDBObjectStore.openCursor()** `IDBObjectStore.openCursor()`用于獲取一個指針對象。 ```javascript IDBObjectStore.openCursor() ``` 指針對象可以用來遍歷數據。該對象也是異步的,有自己的`success`和`error`事件,可以對它們指定監聽函數。 ```javascript var t = db.transaction(['test'], 'readonly'); var store = t.objectStore('test'); var cursor = store.openCursor(); cursor.onsuccess = function (event) { var res = event.target.result; if (res) { console.log('Key', res.key); console.dir('Data', res.value); res.continue(); } } ``` 監聽函數接受一個事件對象作為參數,該對象的`target.result`屬性指向當前數據記錄。該記錄的`key`和`value`分別返回主鍵和鍵值(即實際存入的數據)。`continue()`方法將光標移到下一個數據對象,如果當前數據對象已經是最后一個數據了,則光標指向`null`。 `openCursor()`方法的第一個參數是主鍵值,或者一個 IDBKeyRange 對象。如果指定該參數,將只處理包含指定主鍵的記錄;如果省略,將處理所有的記錄。該方法還可以接受第二個參數,表示遍歷方向,默認值為`next`,其他可能的值為`prev`、`nextunique`和`prevunique`。后兩個值表示如果遇到重復值,會自動跳過。 **(14)IDBObjectStore.openKeyCursor()** `IDBObjectStore.openKeyCursor()`用于獲取一個主鍵指針對象。 ```javascript IDBObjectStore.openKeyCursor() ``` ## IDBTransaction 對象 IDBTransaction 對象用來異步操作數據庫事務,所有的讀寫操作都要通過這個對象進行。 `IDBDatabase.transaction()`方法返回的就是一個 IDBTransaction 對象。 ```javascript var db; var DBOpenRequest = window.indexedDB.open('demo', 1); DBOpenRequest.onsuccess = function(event) { db = DBOpenRequest.result; var transaction = db.transaction(['demo'], 'readwrite'); transaction.oncomplete = function (event) { console.log('transaction success'); }; transaction.onerror = function (event) { console.log('transaction error: ' + transaction.error); }; var objectStore = transaction.objectStore('demo'); var objectStoreRequest = objectStore.add({ foo: 1 }); objectStoreRequest.onsuccess = function (event) { console.log('add data success'); }; }; ``` 事務的執行順序是按照創建的順序,而不是發出請求的順序。 ```javascript var trans1 = db.transaction('foo', 'readwrite'); var trans2 = db.transaction('foo', 'readwrite'); var objectStore2 = trans2.objectStore('foo') var objectStore1 = trans1.objectStore('foo') objectStore2.put('2', 'key'); objectStore1.put('1', 'key'); ``` 上面代碼中,`key`對應的鍵值最終是`2`,而不是`1`。因為事務`trans1`先于`trans2`創建,所以首先執行。 注意,事務有可能失敗,只有監聽到事務的`complete`事件,才能保證事務操作成功。 IDBTransaction 對象有以下屬性。 - `IDBTransaction.db`:返回當前事務所在的數據庫對象 IDBDatabase。 - `IDBTransaction.error`:返回當前事務的錯誤。如果事務沒有結束,或者事務成功結束,或者被手動終止,該方法返回`null`。 - `IDBTransaction.mode`:返回當前事務的模式,默認是`readonly`(只讀),另一個值是`readwrite`。 - `IDBTransaction.objectStoreNames`:返回一個類似數組的對象 DOMStringList,成員是當前事務涉及的對象倉庫的名字。 - `IDBTransaction.onabort`:指定`abort`事件(事務中斷)的監聽函數。 - `IDBTransaction.oncomplete`:指定`complete`事件(事務成功)的監聽函數。 - `IDBTransaction.onerror`:指定`error`事件(事務失敗)的監聽函數。 IDBTransaction 對象有以下方法。 - `IDBTransaction.abort()`:終止當前事務,回滾所有已經進行的變更。 - `IDBTransaction.objectStore(name)`:返回指定名稱的對象倉庫 IDBObjectStore。 ## IDBIndex 對象 IDBIndex 對象代表數據庫的索引,通過這個對象可以獲取數據庫里面的記錄。數據記錄的主鍵默認就是帶有索引,IDBIndex 對象主要用于通過除主鍵以外的其他鍵,建立索引獲取對象。 IDBIndex 是持久性的鍵值對存儲。只要插入、更新或刪除數據記錄,引用的對象庫中的記錄,索引就會自動更新。 `IDBObjectStore.index()`方法可以獲取 IDBIndex 對象。 ```javascript var transaction = db.transaction(['contactsList'], 'readonly'); var objectStore = transaction.objectStore('contactsList'); var myIndex = objectStore.index('lName'); myIndex.openCursor().onsuccess = function (event) { var cursor = event.target.result; if (cursor) { var tableRow = document.createElement('tr'); tableRow.innerHTML = '<td>' + cursor.value.id + '</td>' + '<td>' + cursor.value.lName + '</td>' + '<td>' + cursor.value.fName + '</td>' + '<td>' + cursor.value.jTitle + '</td>' + '<td>' + cursor.value.company + '</td>' + '<td>' + cursor.value.eMail + '</td>' + '<td>' + cursor.value.phone + '</td>' + '<td>' + cursor.value.age + '</td>'; tableEntry.appendChild(tableRow); cursor.continue(); } else { console.log('Entries all displayed.'); } }; ``` IDBIndex 對象有以下屬性。 - `IDBIndex.name`:字符串,索引的名稱。 - `IDBIndex.objectStore`:索引所在的對象倉庫。 - `IDBIndex.keyPath`:索引的主鍵。 - `IDBIndex.multiEntry`:布爾值,針對`keyPath`為數組的情況,如果設為`true`,創建數組時,每個數組成員都會有一個條目,否則每個數組都只有一個條目。 - `IDBIndex.unique`:布爾值,表示創建索引時是否允許相同的主鍵。 IDBIndex 對象有以下方法,它們都是異步的,立即返回的都是一個 IDBRequest 對象。 - `IDBIndex.count()`:用來獲取記錄的數量。它可以接受主鍵或 IDBKeyRange 對象作為參數,這時只返回符合主鍵的記錄數量,否則返回所有記錄的數量。 - `IDBIndex.get(key)`:用來獲取符合指定主鍵的數據記錄。 - `IDBIndex.getKey(key)`:用來獲取指定的主鍵。 - `IDBIndex.getAll()`:用來獲取所有的數據記錄。它可以接受兩個參數,都是可選的,第一個參數用來指定主鍵,第二個參數用來指定返回記錄的數量。如果省略這兩個參數,則返回所有記錄。由于獲取成功時,瀏覽器必須生成所有對象,所以對性能有影響。如果數據集比較大,建議使用 IDBCursor 對象。 - `IDBIndex.getAllKeys()`:該方法與`IDBIndex.getAll()`方法相似,區別是獲取所有主鍵。 - `IDBIndex.openCursor()`:用來獲取一個 IDBCursor 對象,用來遍歷索引里面的所有條目。 - `IDBIndex.openKeyCursor()`:該方法與`IDBIndex.openCursor()`方法相似,區別是遍歷所有條目的主鍵。 ## IDBCursor 對象 IDBCursor 對象代表指針對象,用來遍歷數據倉庫(IDBObjectStore)或索引(IDBIndex)的記錄。 IDBCursor 對象一般通過`IDBObjectStore.openCursor()`方法獲得。 ```javascript var transaction = db.transaction(['rushAlbumList'], 'readonly'); var objectStore = transaction.objectStore('rushAlbumList'); objectStore.openCursor(null, 'next').onsuccess = function(event) { var cursor = event.target.result; if (cursor) { var listItem = document.createElement('li'); listItem.innerHTML = cursor.value.albumTitle + ', ' + cursor.value.year; list.appendChild(listItem); console.log(cursor.source); cursor.continue(); } else { console.log('Entries all displayed.'); } }; }; ``` IDBCursor 對象的屬性。 - `IDBCursor.source`:返回正在遍歷的對象倉庫或索引。 - `IDBCursor.direction`:字符串,表示指針遍歷的方向。共有四個可能的值:next(從頭開始向后遍歷)、nextunique(從頭開始向后遍歷,重復的值只遍歷一次)、prev(從尾部開始向前遍歷)、prevunique(從尾部開始向前遍歷,重復的值只遍歷一次)。該屬性通過`IDBObjectStore.openCursor()`方法的第二個參數指定,一旦指定就不能改變了。 - `IDBCursor.key`:返回當前記錄的主鍵。 - `IDBCursor.value`:返回當前記錄的數據值。 - `IDBCursor.primaryKey`:返回當前記錄的主鍵。對于數據倉庫(objectStore)來說,這個屬性等同于 IDBCursor.key;對于索引,IDBCursor.key 返回索引的位置值,該屬性返回數據記錄的主鍵。 IDBCursor 對象有如下方法。 - `IDBCursor.advance(n)`:指針向前移動 n 個位置。 - `IDBCursor.continue()`:指針向前移動一個位置。它可以接受一個主鍵作為參數,這時會跳轉到這個主鍵。 - `IDBCursor.continuePrimaryKey()`:該方法需要兩個參數,第一個是`key`,第二個是`primaryKey`,將指針移到符合這兩個參數的位置。 - `IDBCursor.delete()`:用來刪除當前位置的記錄,返回一個 IDBRequest 對象。該方法不會改變指針的位置。 - `IDBCursor.update()`:用來更新當前位置的記錄,返回一個 IDBRequest 對象。它的參數是要寫入數據庫的新的值。 ## IDBKeyRange 對象 IDBKeyRange 對象代表數據倉庫(object store)里面的一組主鍵。根據這組主鍵,可以獲取數據倉庫或索引里面的一組記錄。 IDBKeyRange 可以只包含一個值,也可以指定上限和下限。它有四個靜態方法,用來指定主鍵的范圍。 - `IDBKeyRange.lowerBound()`:指定下限。 - `IDBKeyRange.upperBound()`:指定上限。 - `IDBKeyRange.bound()`:同時指定上下限。 - `IDBKeyRange.only()`:指定只包含一個值。 下面是一些代碼實例。 ```javascript // All keys ≤ x var r1 = IDBKeyRange.upperBound(x); // All keys < x var r2 = IDBKeyRange.upperBound(x, true); // All keys ≥ y var r3 = IDBKeyRange.lowerBound(y); // All keys > y var r4 = IDBKeyRange.lowerBound(y, true); // All keys ≥ x && ≤ y var r5 = IDBKeyRange.bound(x, y); // All keys > x &&< y var r6 = IDBKeyRange.bound(x, y, true, true); // All keys > x && ≤ y var r7 = IDBKeyRange.bound(x, y, true, false); // All keys ≥ x &&< y var r8 = IDBKeyRange.bound(x, y, false, true); // The key = z var r9 = IDBKeyRange.only(z); ``` `IDBKeyRange.lowerBound()`、`IDBKeyRange.upperBound()`、`IDBKeyRange.bound()`這三個方法默認包括端點值,可以傳入一個布爾值,修改這個屬性。 與之對應,IDBKeyRange 對象有四個只讀屬性。 - `IDBKeyRange.lower`:返回下限 - `IDBKeyRange.lowerOpen`:布爾值,表示下限是否為開區間(即下限是否排除在范圍之外) - `IDBKeyRange.upper`:返回上限 - `IDBKeyRange.upperOpen`:布爾值,表示上限是否為開區間(即上限是否排除在范圍之外) IDBKeyRange 實例對象生成以后,將它作為參數輸入 IDBObjectStore 或 IDBIndex 對象的`openCursor()`方法,就可以在所設定的范圍內讀取數據。 ```javascript var t = db.transaction(['people'], 'readonly'); var store = t.objectStore('people'); var index = store.index('name'); var range = IDBKeyRange.bound('B', 'D'); index.openCursor(range).onsuccess = function (e) { var cursor = e.target.result; if (cursor) { console.log(cursor.key + ':'); for (var field in cursor.value) { console.log(cursor.value[field]); } cursor.continue(); } } ``` IDBKeyRange 有一個實例方法`includes(key)`,返回一個布爾值,表示某個主鍵是否包含在當前這個主鍵組之內。 ```javascript var keyRangeValue = IDBKeyRange.bound('A', 'K', false, false); keyRangeValue.includes('F') // true keyRangeValue.includes('W') // false ``` ## 參考鏈接 - Raymond Camden, [Working With IndexedDB – Part 1](http://net.tutsplus.com/tutorials/javascript-ajax/working-with-indexeddb/) - Raymond Camden, [Working With IndexedDB – Part 2](http://net.tutsplus.com/tutorials/javascript-ajax/working-with-indexeddb-part-2/) - Raymond Camden, [Working With IndexedDB - Part 3](https://code.tutsplus.com/tutorials/working-with-indexeddb-part-3--net-36220) - Tiffany Brown, [An Introduction to IndexedDB](http://dev.opera.com/articles/introduction-to-indexeddb/) - David Fahlander, [Breaking the Borders of IndexedDB](https://hacks.mozilla.org/2014/06/breaking-the-borders-of-indexeddb/) - TutorialsPoint, [HTML5 - IndexedDB](https://www.tutorialspoint.com/html5/html5_indexeddb.htm)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看