本指南涵蓋 IndexedDB API。 我們使用 Jake Archibald 的 已建立索引的資料庫 與 IndexedDB API 非常類似 但使用了承諾 您可以 await
取得更簡潔的語法。這樣可簡化 API 以及維持原本的結構
什麼是 IndexedDB?
IndexedDB 是大規模的 NoSQL 儲存系統 對使用者瀏覽器中的所有資訊除了一般的搜尋、取得和 它更適合用於輸入操作 儲存大量結構化資料
每個 IndexedDB 資料庫都只屬於一個來源 (通常是網站網域或子網域) 表示無法存取或存取 不受其他來源影響其資料儲存空間限制 通常會很大,但也會有,但不同瀏覽器處理限制 以及資料撤銷方式如要瞭解相關資訊,請參閱其他資訊一節 瞭解詳情
IndexedDB 詞彙
- 資料庫
- IndexedDB 的最高層。其中包含物件儲存庫, 包含要保留的資料。您可以建立多個資料庫 你選的名稱
- 物件存放區
- 用來儲存資料的個別值區,類似關聯資料庫中的資料表。 一般來說,每種「類型」 (非 JavaScript 資料) 都有一個物件儲存庫 自訂類型)。與資料庫表格不同的是,JavaScript 資料 儲存庫中的資料類型不需要一致。舉例來說 有一個
people
物件儲存庫,內含三個人的資訊 使用者的年齡屬性可以是53
、'twenty-five'
和unknown
。 - 索引
- 一種物件儲存區,可用來整理其他物件存放區中的資料 (稱為 參照物件儲存庫)。系統會使用索引 以擷取此屬性在物件存放區中的記錄。舉例來說 儲存人員時,建議您日後依名稱、年齡或 最喜歡的動物
- 作業
- 與資料庫的互動。
- 交易
- 包裝一個能確保資料庫的作業或作業群組包裝函式 完整性。如果交易中的其中一項操作失敗,則沒有任何動作失敗 資料庫會回復為交易前的狀態 開始。IndexedDB 中的所有讀取或寫入作業都必須屬於交易的一部分。 如此一來,就能執行不可部分完成的讀取-修改-寫入作業,而不會產生衝突風險 由其他執行緒同時在資料庫中運作。
- 遊標
- 針對資料庫中多筆記錄疊代的機制。
如何查看 IndexedDB 支援
IndexedDB 幾乎可全面支援。 不過,如果您使用的是較舊的瀏覽器,那麼 功能偵測支援,以備不時之需最簡單的方法是查看 window
物件:
function indexedDBStuff () { // Check for IndexedDB support: if (!('indexedDB' in window)) { // Can't use IndexedDB console.log("This browser doesn't support IndexedDB"); return; } else { // Do IndexedDB stuff here: // ... } } // Run IndexedDB code: indexedDBStuff();
如何開啟資料庫
透過 IndexedDB,您可以使用任何名稱建立多個資料庫。如果 您嘗試開啟資料庫時不存在 如要開啟資料庫,請使用 idb
程式庫中的 openDB()
方法:
import {openDB} from 'idb'; async function useDB () { // Returns a promise, which makes `idb` usable with async-await. const dbPromise = await openDB('example-database', version, events); } useDB();
這個方法會傳回可解析為資料庫物件的承諾。使用 openDB()
方法,提供名稱、版本號碼和要設定的事件物件 以及資料庫。
以下是 openDB()
方法的範例:
import {openDB} from 'idb'; async function useDB () { // Opens the first version of the 'test-db1' database. // If the database does not exist, it will be created. const dbPromise = await openDB('test-db1', 1); } useDB();
將檢查 IndexedDB 的支援置於匿名函式的最上方。這個 如果瀏覽器不支援 IndexedDB,就會結束函式。如果函式可以 繼續,這個方法會呼叫 openDB()
方法,開啟名為 'test-db1'
的資料庫。 在這個範例中,選擇性的事件物件並未經過保留, 但您需要指定這個值,才能利用索引資料庫執行任何有意義的工作。
如何使用物件儲存庫
索引資料庫包含一或多個物件儲存庫, 資料欄,另一個是該鍵相關資料的資料欄。
建立物件儲存庫
結構良好的 IndexedDB 資料庫應針對每種類型各建立一個物件儲存庫 需要保存的資料數量例如:使用者持續瀏覽網站 設定檔和附註可能具有包含 person
的 people
物件儲存庫 和包含 note
物件的 notes
物件儲存庫。
為確保資料庫完整性,您只能在 openDB()
呼叫中的事件物件。事件物件公開 upgrade()
方法可讓您建立物件儲存庫在 createObjectStore()
敬上 upgrade()
方法中的方法建立物件儲存庫:
import {openDB} from 'idb'; async function createStoreInDB () { const dbPromise = await openDB('example-database', 1, { upgrade (db) { // Creates an object store: db.createObjectStore('storeName', options); } }); } createStoreInDB();
這個方法使用物件儲存庫的名稱,以及選用設定 物件,可讓您定義物件儲存區的各種屬性。
以下範例說明如何使用 createObjectStore()
:
import {openDB} from 'idb'; async function createStoreInDB () { const dbPromise = await openDB('test-db1', 1, { upgrade (db) { console.log('Creating a new object store...'); // Checks if the object store exists: if (!db.objectStoreNames.contains('people')) { // If the object store does not exist, create it: db.createObjectStore('people'); } } }); } createStoreInDB();
在這個範例中,事件物件會傳遞至 openDB()
方法,以便建立 物件存放區;和先前一樣,建立物件儲存庫的工作即完成 事件物件的 upgrade()
方法中。不過,由於瀏覽器 如果嘗試建立已存在的物件儲存庫, 將 createObjectStore()
方法包裝在用於檢查的 if
陳述式中 物件儲存空間是否存在在 if
區塊中,呼叫 createObjectStore()
:建立名為 'firstOS'
的物件儲存庫。
如何定義主鍵
定義物件儲存時,您可以定義如何利用 如果是透過主鍵提交儲存庫如要定義主鍵,您可以定義 金鑰路徑或金鑰產生器
金鑰路徑是一種永遠存在且包含不重複值的屬性。適用對象 舉例來說,如果是 people
物件儲存庫,您可以選擇 做為金鑰路徑:
import {openDB} from 'idb'; async function createStoreInDB () { const dbPromise = await openDB('test-db2', 1, { upgrade (db) { if (!db.objectStoreNames.contains('people')) { db.createObjectStore('people', { keyPath: 'email' }); } } }); } createStoreInDB();
這個範例會建立名為 'people'
的物件儲存庫,並指派 email
將屬性做為 keyPath
選項中的主鍵。
您也可以使用金鑰產生器,例如 autoIncrement
。金鑰產生器 會為物件儲存區中的每個物件建立專屬的值。根據預設 如未指定索引鍵,IndexedDB 會建立索引鍵,並分開儲存 從資料中取用
以下範例會建立名為 'notes'
的物件儲存庫,並設定 自動遞增的主鍵:
import {openDB} from 'idb'; async function createStoreInDB () { const dbPromise = await openDB('test-db2', 1, { upgrade (db) { if (!db.objectStoreNames.contains('notes')) { db.createObjectStore('notes', { autoIncrement: true }); } } }); } createStoreInDB();
下例與先前的範例類似,但這次的例子 自動遞增值已明確指派給名為 'id'
的屬性。
import {openDB} from 'idb'; async function createStoreInDB () { const dbPromise = await openDB('test-db2', 1, { upgrade (db) { if (!db.objectStoreNames.contains('logs')) { db.createObjectStore('logs', { keyPath: 'id', autoIncrement: true }); } } }); } createStoreInDB();
請根據您的資料內容,選擇正確的金鑰定義方法。如果您的 資料的屬性不會重複,您可以將其設為 keyPath
, 強制規定的唯一性否則,請使用自動遞增值。
以下程式碼會建立三個物件儲存庫,展示 定義物件存放區中的主鍵:
import {openDB} from 'idb'; async function createStoresInDB () { const dbPromise = await openDB('test-db2', 1, { upgrade (db) { if (!db.objectStoreNames.contains('people')) { db.createObjectStore('people', { keyPath: 'email' }); } if (!db.objectStoreNames.contains('notes')) { db.createObjectStore('notes', { autoIncrement: true }); } if (!db.objectStoreNames.contains('logs')) { db.createObjectStore('logs', { keyPath: 'id', autoIncrement: true }); } } }); } createStoresInDB();
如何定義索引
索引是一種物件儲存庫,用來從參照擷取資料 依據指定的屬性儲存物件索引位於參照物件中 儲存和包含相同的資料,但會使用指定的屬性做為其屬性 ,而不是參照儲存庫的主鍵。索引必須建立於 您可以建立物件儲存區,還能針對 資料。
如要建立索引,請呼叫 createIndex()
方法:
import {openDB} from 'idb'; async function createIndexInStore() { const dbPromise = await openDB('storeName', 1, { upgrade (db) { const objectStore = db.createObjectStore('storeName'); objectStore.createIndex('indexName', 'property', options); } }); } createIndexInStore();
這個方法會建立並傳回索引物件。已啟用的 createIndex()
方法 物件儲存庫的例項會採用新索引的名稱做為第一個 第二個引數則參照要儲存的資料上的屬性 索引。最後的引數則可讓您定義兩個選項 索引運作次數:unique
和 multiEntry
。如果將 unique
設為 true
, 索引不允許單一鍵使用重複的值。下一步,multiEntry
決定已建立索引的屬性為陣列時,createIndex()
的行為。如果 設為 true
,createIndex()
會在每個陣列的索引中新增項目 元素。否則,會新增一個包含陣列的項目。
範例如下:
import {openDB} from 'idb'; async function createIndexesInStores () { const dbPromise = await openDB('test-db3', 1, { upgrade (db) { if (!db.objectStoreNames.contains('people')) { const peopleObjectStore = db.createObjectStore('people', { keyPath: 'email' }); peopleObjectStore.createIndex('gender', 'gender', { unique: false }); peopleObjectStore.createIndex('ssn', 'ssn', { unique: true }); } if (!db.objectStoreNames.contains('notes')) { const notesObjectStore = db.createObjectStore('notes', { autoIncrement: true }); notesObjectStore.createIndex('title', 'title', { unique: false }); } if (!db.objectStoreNames.contains('logs')) { const logsObjectStore = db.createObjectStore('logs', { keyPath: 'id', autoIncrement: true }); } } }); } createIndexesInStores();
在這個範例中,'people'
和 'notes'
物件儲存庫具有索引。目的地: 建立索引,請先指派 createObjectStore()
的結果 (物件 儲存物件) 新增至變數中,因此您可以在該變數上呼叫 createIndex()
。
如何使用資料
本節說明如何建立、讀取、更新及刪除資料。這些 都是非同步作業,使用 IndexedDB API 的承諾 要求。這樣可簡化 API。與其監聽 要求,您可以對呼叫函式所傳回的資料庫物件呼叫 .then()
。 用於與資料庫互動的 openDB()
方法,或 await
其 建立。
凡是已建立索引資料庫中的資料作業,都是在交易中執行。每項 作業的格式如下:
- 取得資料庫物件。
- 開啟資料庫上的交易。
- 在交易中開啟物件儲存庫。
- 在物件儲存庫執行作業。
交易可視為作業或群組周圍的安全包裝函式 作業。如果交易中的任一動作失敗,則所有 交易專屬於一或多個物件存放區 自訂範本可以是唯讀或讀取 以及寫入與寫入這代表交易內的作業是否讀取了 或對資料庫進行變更
建立資料
如要建立資料,請呼叫 add()
方法並傳入您要新增的資料。add()
方法的第一個引數是您要加入資料的物件儲存庫,而 第二個引數是包含所需欄位和關聯資料的物件 。以下為最簡單的範例,只會新增一列資料:
import {openDB} from 'idb'; async function addItemToStore () { const db = await openDB('example-database', 1); await db.add('storeName', { field: 'data' }); } addItemToStore();
每次 add()
呼叫都會在交易中發生,因此即使承諾解析 但這不表示作業成功。為確保 執行新增作業後,您必須檢查整個 交易已透過 transaction.done()
方法完成。這是 保證會在交易自行完成時解析,如果 交易錯誤。您必須對所有「寫入」執行這項檢查作業 因為這是得知資料庫變更的唯一方法 。
以下程式碼顯示如何在交易中使用 add()
方法:
import {openDB} from 'idb'; async function addItemsToStore () { const db = await openDB('test-db4', 1, { upgrade (db) { if (!db.objectStoreNames.contains('foods')) { db.createObjectStore('foods', { keyPath: 'name' }); } } }); // Create a transaction on the 'foods' store in read/write mode: const tx = db.transaction('foods', 'readwrite'); // Add multiple items to the 'foods' store in a single transaction: await Promise.all([ tx.store.add({ name: 'Sandwich', price: 4.99, description: 'A very tasty sandwich!', created: new Date().getTime(), }), tx.store.add({ name: 'Eggs', price: 2.99, description: 'Some nice eggs you can cook up!', created: new Date().getTime(), }), tx.done ]); } addItemsToStore();
開啟資料庫後 (並視需要建立物件儲存庫),您需要 對應用程式呼叫 transaction()
方法,即可開啟交易。這個方法 表示您想交易的商店和交通方式 在這個範例中,我們要寫入商店 會指定 'readwrite'
。
下一步是開始在交易中新增商品。 在上述範例中,我們要處理 'foods'
上的三項作業 例如:
- 新增美味三明治的記錄。
- 正在新增幾顆能量蛋的記錄。
- 表示交易已完成 (
tx.done
)。
由於所有這些行動都是以承諾為基礎,因此需要等待 以完成這些步驟將這些承諾傳遞至 Promise.all
敬上 是符合人體工學的 好方法Promise.all
可接受 保證並結束之後。
針對要新增的兩筆記錄,交易例項的 store
介面 呼叫 add()
並將資料傳遞至該函式。你可以await
Promise.all
通話 這項作業會在交易完成時結束
讀取資料
如要讀取資料,請呼叫 get()
方法是使用 openDB()
方法擷取。 get()
會使用商店的名稱,以及所建立物件的主鍵值 要擷取的內容基本範例如下:
import {openDB} from 'idb'; async function getItemFromStore () { const db = await openDB('example-database', 1); // Get a value from the object store by its primary key value: const value = await db.get('storeName', 'unique-primary-key-value'); } getItemFromStore();
和 add()
一樣,get()
方法會傳回承諾值,因此您可以 await
您也可以使用承諾的 .then()
回呼。
以下範例在 'test-db4'
資料庫的get()
'foods'
物件儲存庫,透過 'name'
主鍵取得單一資料列:
import {openDB} from 'idb'; async function getItemFromStore () { const db = await openDB('test-db4', 1); const value = await db.get('foods', 'Sandwich'); console.dir(value); } getItemFromStore();
從資料庫擷取單一資料列的方法非常簡單:開放 並指定該資料列的物件儲存庫和主鍵值 從中取得資料get()
方法會傳回承諾值,因此您可以 await
。
更新資料
如要更新資料,請呼叫 put()
方法。put()
方法與 add()
方法類似 也可以取代 add()
,藉此建立資料。以下舉例說明 根據主鍵值,使用 put()
更新物件儲存庫中的資料列:
import {openDB} from 'idb'; async function updateItemInStore () { const db = await openDB('example-database', 1); // Update a value from in an object store with an inline key: await db.put('storeName', { inlineKeyName: 'newValue' }); // Update a value from in an object store with an out-of-line key. // In this case, the out-of-line key value is 1, which is the // auto-incremented value. await db.put('otherStoreName', { field: 'value' }, 1); } updateItemInStore();
與其他方法一樣,這個方法會傳回承諾值。你也可以將 put()
用於以下用途: 交易的一部分以下是使用舊版 'foods'
商店的範例 更新三明治和雞蛋的價格:
import {openDB} from 'idb'; async function updateItemsInStore () { const db = await openDB('test-db4', 1); // Create a transaction on the 'foods' store in read/write mode: const tx = db.transaction('foods', 'readwrite'); // Update multiple items in the 'foods' store in a single transaction: await Promise.all([ tx.store.put({ name: 'Sandwich', price: 5.99, description: 'A MORE tasty sandwich!', updated: new Date().getTime() // This creates a new field }), tx.store.put({ name: 'Eggs', price: 3.99, description: 'Some even NICER eggs you can cook up!', updated: new Date().getTime() // This creates a new field }), tx.done ]); } updateItemsInStore();
項目更新方式取決於您設定金鑰的方式。如果您設定了 keyPath
, 物件儲存庫中的每個資料列都會與一個內嵌鍵建立關聯。上述 範例會根據這個鍵更新資料列 在此情況下,您將需要指定該鍵,以更新 GRU 狀態中的 物件儲存空間你也可以建立脫行金鑰 autoIncrement
做為主鍵。
刪除資料
如要刪除資料,請呼叫 delete()
方法:
import {openDB} from 'idb'; async function deleteItemFromStore () { const db = await openDB('example-database', 1); // Delete a value await db.delete('storeName', 'primary-key-value'); } deleteItemFromStore();
和 add()
和 put()
一樣,您可以在交易中使用以下內容:
import {openDB} from 'idb'; async function deleteItemsFromStore () { const db = await openDB('test-db4', 1); // Create a transaction on the 'foods' store in read/write mode: const tx = db.transaction('foods', 'readwrite'); // Delete multiple items from the 'foods' store in a single transaction: await Promise.all([ tx.store.delete('Sandwich'), tx.store.delete('Eggs'), tx.done ]); } deleteItemsFromStore();
資料庫互動的結構與其他 作業。別忘了,請按照下列步驟檢查整筆交易 包括您傳遞給 Promise.all
的陣列中 tx.done
方法。
取得所有資料
到目前為止,您一次只能從商店擷取一個物件。你也可以 使用 getAll()
方法或遊標。
getAll()
方法
如要擷取物件儲存庫的所有資料,最簡單的方法是呼叫 getAll()
,如下所示:
import {openDB} from 'idb'; async function getAllItemsFromStore () { const db = await openDB('test-db4', 1); // Get all values from the designated object store: const allValues = await db.getAll('storeName'); console.dir(allValues); } getAllItemsFromStore();
這個方法會傳回物件儲存庫中的所有物件,但沒有限制 隨便啦這是從物件儲存庫中取得所有值最直接的方式 同時也缺乏彈性
import {openDB} from 'idb'; async function getAllItemsFromStore () { const db = await openDB('test-db4', 1); // Get all values from the designated object store: const allValues = await db.getAll('foods'); console.dir(allValues); } getAllItemsFromStore();
本範例會在 'foods'
物件儲存庫上呼叫 getAll()
。這會傳回 來自 'foods'
的物件,依主鍵排序。
如何使用遊標
遊標是更靈活的擷取多個物件方法。遊標選取 或逐一建立索引 以及這些資料遊標與其他資料庫作業一樣 做為交易基礎
如要建立遊標,請呼叫 openCursor()
作為交易的一部分從以下位置使用 'foods'
商店: 先前的例子,這就是如何將遊標移到 物件儲存庫則:
import {openDB} from 'idb'; async function getAllItemsFromStoreWithCursor () { const db = await openDB('test-db4', 1); const tx = await db.transaction('foods', 'readonly'); // Open a cursor on the designated object store: let cursor = await tx.store.openCursor(); // Iterate on the cursor, row by row: while (cursor) { // Show the data in the row at the current cursor position: console.log(cursor.key, cursor.value); // Advance the cursor to the next row: cursor = await cursor.continue(); } } getAllItemsFromStoreWithCursor();
在此情況下,交易會以 'readonly'
模式開啟, 系統會呼叫 openCursor
方法。在後續的 while
迴圈中, 遊標目前位置可以讀取其 key
和 value
屬性,以及 還是能以最合理的方式 應用程式。準備就緒後,即可呼叫 cursor
物件的 continue()
方法前往下一列,而 while
迴圈會在遊標時終止 輸出到資料集結尾
使用含有範圍和索引的遊標
索引可讓您以非 主鍵。您可以在任何屬性 (成為 keyPath
的屬性) 建立索引 為索引指定範圍,然後在 使用 getAll()
或遊標的範圍。
請使用 IDBKeyRange
物件定義範圍。和下列任一條件 方法:
upperBound()
。lowerBound()
。bound()
(兩者皆是)。only()
。includes()
。
upperBound()
和 lowerBound()
方法會指定上限與下限 範圍內
IDBKeyRange.lowerBound(indexKey);
或:
IDBKeyRange.upperBound(indexKey);
每個引數都會擷取一個引數:所需項目的索引 keyPath
值 來指定上限或下限
bound()
方法會指定上限與下限:
IDBKeyRange.bound(lowerIndexKey, upperIndexKey);
根據預設,這些函式的範圍包含 指定為範圍上限的資料如果不想看到這些值 將 true
做為第二個引數傳遞,即可將範圍指定為「專屬」。 lowerBound()
或 upperBound()
,或是 bound()
,分別適用於下限和上限。
下一個範例使用 'foods'
物件中 'price'
屬性的索引 也就是經過處理且會導入模型的資料 接著再透過特徵儲存庫與他人分享商店現在還附加了表單,其中包含了 目標範圍使用以下程式碼尋找含有 並設定下列價格:
import {openDB} from 'idb'; async function searchItems (lower, upper) { if (!lower === '' && upper === '') { return; } let range; if (lower !== '' && upper !== '') { range = IDBKeyRange.bound(lower, upper); } else if (lower === '') { range = IDBKeyRange.upperBound(upper); } else { range = IDBKeyRange.lowerBound(lower); } const db = await openDB('test-db4', 1); const tx = await db.transaction('foods', 'readonly'); const index = tx.store.index('price'); // Open a cursor on the designated object store: let cursor = await index.openCursor(range); if (!cursor) { return; } // Iterate on the cursor, row by row: while (cursor) { // Show the data in the row at the current cursor position: console.log(cursor.key, cursor.value); // Advance the cursor to the next row: cursor = await cursor.continue(); } } // Get items priced between one and four dollars: searchItems(1.00, 4.00);
程式碼範例會先取得上限的值,並檢查是否存在限制 個值。下一個程式碼區塊會決定要使用哪種方法限制 做出決定在資料庫互動中,開啟 接著,在物件儲存庫中開啟 'price'
索引。 'price'
索引可讓您按價格搜尋商品。
接著,程式碼會在索引上開啟遊標,並傳入該範圍。遊標 會傳回代表範圍內第一個物件的保證;如果傳回,則傳回 undefined
這個範圍內沒有任何資料cursor.continue()
方法會傳回 並持續不斷地循環顯示,直到進入下一個物件 達到範圍結尾處
資料庫版本管理
呼叫 openDB()
方法時,您可以指定資料庫版本號碼 。在本指南的所有示例中,版本都採用 設為 1
,但如果需要將資料庫升級至新版本 以某種方式進行修改如果指定的版本大於 現有資料庫,而事件物件中的 upgrade
回呼會執行。 可讓您在資料庫中加入新的物件儲存庫與索引。
upgrade
回呼中的 db
物件具有特殊的 oldVersion
屬性。 ,指出瀏覽器可存取的資料庫版本號碼。 您可以將此版本號碼傳遞至 switch
陳述式,以執行 會因現有的資料庫版本 而在 upgrade
回呼中 號碼。範例如下:
import {openDB} from 'idb'; const db = await openDB('example-database', 2, { upgrade (db, oldVersion) { switch (oldVersion) { case 0: // Create first object store: db.createObjectStore('store', { keyPath: 'name' }); case 1: // Get the original object store, and create an index on it: const tx = await db.transaction('store', 'readwrite'); tx.store.createIndex('name', 'name'); } } });
以下範例會將資料庫的最新版本設定為 2
。當此代碼 瀏覽器尚未有資料庫,因此 oldVersion
為 0
,switch
陳述式從 case 0
開始。在這個範例中 並將 'store'
物件儲存庫新增至資料庫。
重點:在 switch
陳述式中,每個 case
後面通常都有 break
但這不是這裡的用意 這樣一來 資料庫落後數個版本;如果找不到,程式碼會繼續執行 直到更新到 case
為止。在這個範例中 瀏覽器會繼續透過 case 1
建立 name
索引, store
物件儲存庫。
如要在 'store'
物件儲存庫中建立 'description'
索引,請更新 並新增 case
區塊,如下所示:
import {openDB} from 'idb'; const db = await openDB('example-database', 3, { upgrade (db, oldVersion) { switch (oldVersion) { case 0: // Create first object store: db.createObjectStore('store', { keyPath: 'name' }); case 1: // Get the original object store, and create an index on it: const tx = await db.transaction('store', 'readwrite'); tx.store.createIndex('name', 'name'); case 2: const tx = await db.transaction('store', 'readwrite'); tx.store.createIndex('description', 'description'); } } });
如果您在前一個範例中建立的資料庫仍存在瀏覽器中, 當系統執行此項目時,oldVersion
為 2
。瀏覽器會略過 case 0
和 case 1
,並執行 case 2
中的程式碼,藉此建立 description
索引。之後,瀏覽器的資料庫位於第 3 版,且內含 store
擁有 name
和 description
索引的物件儲存庫。
延伸閱讀
下列資源提供使用 IndexedDB 的更多資訊和背景資訊。