分享程式代碼相關筆記
目前文章總數:157 篇
最後更新:2024年 12月 07日
IndexedDB 為用戶端的儲存用 API,可用於大量的結構化資料,並透過索引功能而高效率搜尋資料。
DOM Storage (en-US) 適合儲存較少量的資料;IndexedDB 則適合大量結構化資料的儲存方案。
上述來自官網: MDN(Mozilla Developer Network)
大意:可以幫每個用戶用瀏覽器時建立 Indexed 客戶端資料庫
另外具有以下特性:
1. 非同步事務 |
2. 可建立索引 |
3. 客戶端數據庫 |
在使用前應評估以下,如果符合在使用:
項目 | 說明 | |
---|---|---|
靜態離線網站 | : | 開發的這個網頁、網站可以離線操作,如一個手冊說明網站 |
高效搜尋功能 | : | 可以將靜態的資料轉為 IndexedDB 資料庫,然後達到快速查詢 |
減少伺服器負擔 | : | 資料為固定的情況下,可以對伺服器取得資料,將資料保存在前端瀏覽器 |
無論哪種,都是為了資料可重複在瀏覽器上瀏覽,提升效能
以下是符合評估條件後,要使用前仍會遺留的缺點:
項目 | 說明 | |
---|---|---|
1. 複雜的代碼邏輯 | : | 要從手冊中了解整個資料庫生命周期,並且操作皆為非同步,例如要遵守 Onsuccess 的返回後操作等 |
2. 瀏覽器兼容性 | : | 不是所有瀏覽器版本都兼容,使用前需評估用戶群 |
3. 首次載入耗時 | : | 在初始化資料庫階段,會經歷:建庫-> 檢查版本 -> 建索引 -> 建資料 至少 1 秒 |
4. 儲存空間限制 | : | 每個瀏覽器允許儲存的空間不同,但最後仍受限使用者的硬碟空間(包含手機空間) |
以下是截至 2024/03/23 前的 Can I Use 網站記錄資料
如果用戶群是使用 IE 9 以前的瀏覽器,會造成 Javascript 報錯無法使用
基於 Demo範例:連結
有以下代碼:
<button id="createDataBaseButton">1. 建立資料庫</button><br /><br />
const databaseName = "myDatabase";
// 1. 建立資料庫
function createDataBase() {
// 打開資料庫
var request = indexedDB.open(databaseName, 1);
document.getElementById('messageText').innerHTML += "1. 資料庫已建立" + '<br />';
// 資料庫版本升級處理
request.onupgradeneeded = function (event) {
var db = event.target.result;
createIndexStruct(db);
};
// 資料庫打開成功處理
request.onsuccess = function (event) {
};
}
需要注意每當開啟時,會先檢查 request.onupgradeneeded() 版本號,且版本號為整數型態
由 indexedDB.open(databaseName, 1); 觸發,對應 Fucntion 參數
indexedDB.open(使用的資料庫名稱, 版本號)
在 Demo 代碼中,點擊按鈕,產生 IndexedDB 資料庫
按下鍵盤F12 開啟開發者模式,可以看到在
應用程式 -> IndexedDB 有建立的資料庫
在建立資料庫時,依照 MDN 的手冊說明,索引應在觸發版本檢查時建立
因此 onupgradeneeded 內建立索引代碼如下:
// 2. 建立資料庫索引
function createIndexStruct(db) {
// autoIncrement: true 表示自動新增ID
var objectStore = db.createObjectStore("customers", { autoIncrement: true });
objectStore.createIndex("name", "name", { unique: false });
document.getElementById('messageText').innerHTML += "2. 索引已建立" +'<br /><br />';
}
索引的建立應該依照業務邏輯查詢功能而建立,可參考 MDN 結構化資料庫-索引
基於 Demo範例:連結
<button id="insertRowdataButton">3-1. 新增、修改資料與查詢 - 新增資料</button><br /><br />
const databaseName = "myDatabase";
// 3. 新增、修改資料與查詢
function insertRowdata() {
// 連線資料庫、開啟
var request = indexedDB.open(databaseName, 1);
request.onsuccess = function (event) {
var db = event.target.result;
// 創建事務並獲取物件存儲區
var transaction = db.transaction("customers", "readwrite");
var objectStore = transaction.objectStore("customers");
// 新增資料
var name = 'John';
var email = "john@example.com";
var request = objectStore.add({ name: name, email: email });
request.onsuccess = function (event) {
document.getElementById('messageText').innerHTML += "3.1 新增資料成功! 資料=> " + '<br />' + "name:" + name + '<br />' + ' email:' + email + '<br /><br />';
};
};
}
操作後預期會產生一筆資料,注意資料的結構已從建立資料庫時建立過
因此才能插入 Object 型態的 objectStore.add({ name: name, email: email });
在 Demo 代碼中,點擊按鈕,產生新增一筆資料
按下鍵盤F12 開啟開發者模式,可以看到資料已建立
基於 Demo範例:連結
<button id="updateRowdataButton">3-2. 新增、修改資料與查詢 - 修改資料</button><br /><br />
const databaseName = "myDatabase";
// 修改資料
function updateRowdata() {
// 連線資料庫、開啟
var request = indexedDB.open(databaseName, 1);
request.onsuccess = function (event) {
var db = event.target.result;
// 創建事務並獲取物件存儲區
var transaction = db.transaction("customers", "readwrite");
var objectStore = transaction.objectStore("customers");
// 取得要修改的資料 - Id = 1的資料
var getRequest = objectStore.get(1); // 修改此處變數名稱
getRequest.onsuccess = function (event) {
var data = event.target.result;
if (data) {
// 修改資料
var tempData = data;
tempData.name = "John Doe";
// 刪除舊的資料
objectStore.delete(1);
var putRequest = objectStore.put(tempData);
putRequest.onsuccess = function (event) {
document.getElementById('messageText').innerHTML += "3.2 修改資料成功! 修改的資料=> " + '<br />' + " name:" + data.name + '<br /><br />';
};
}
};
}
}
IndexedDB 如果要修改資料,需要將舊的資料刪除,然後插入,才可視為修改。
因為在 IndexedDB 中,一但數據存儲,主鍵是不可以變更。所以無法直接透過主鍵來更新資料。
在 Demo 代碼中,點擊按鈕,修改資料
按下鍵盤F12 開啟開發者模式,可以看到資料修改提示
基於 Demo範例:連結
<button id="queryRowdataButton">3-3. 新增、修改資料與查詢 - 查詢資料</button><br /><br />
const databaseName = "myDatabase";
// 查詢資料
function queryRowdata() {
// 連線資料庫、開啟
var request = indexedDB.open(databaseName, 1);
request.onsuccess = function (event) {
var db = event.target.result;
// 創建讀取事務並獲取物件存儲區
var transaction = db.transaction(["customers"], "readonly");
var objectStore = transaction.objectStore("customers");
// 取得資料 - 所有資料的取法
var requestGet = objectStore.getAll();
// 查詢資料
requestGet.onsuccess = function (event) {
var customers = event.target.result;
document.getElementById('messageText').innerHTML += "3.3 查詢結果:"+ '<br />' ;
if (customers && customers.length > 0) {
customers.forEach(function (customer) {
document.getElementById('messageText').innerHTML += "name:" + customer.name + '<br />' + ' email:' + customer.email + '<br /><br />';
});
} else {
document.getElementById('messageText').innerHTML += "查無資料" + '<br /><br />';
}
};
}
}
查詢資料這邊使用的 getAll() 將所有資料取出,常用的有以下:
項目 | 說明 | |
---|---|---|
getAll() | : | 所有資料 |
get(1) | : | 取得主鍵 Id 為 1 的資料 |
getAllKeys() | : | 取得所有 [主鍵] |
openCursor() | : | 遍歷每筆資料 |
在 Demo 代碼中,點擊按鈕,查詢顯示結果
基於 Demo範例:連結
<button id="deleteRowdataButton">3-4. 新增、修改資料與查詢 - 刪除資料</button><br /><br />
const databaseName = "myDatabase";
// 3. 刪除資料
function deleteRowdata() {
// 打開數據庫連接
var request = indexedDB.open(databaseName, 1);
request.onsuccess = function (event) {
var db = event.target.result;
// 創建讀取事務並獲取物件存儲區
var transaction = db.transaction("customers", "readwrite");
var objectStore = transaction.objectStore("customers");
// 刪除資料 - 示意用:因為修改後,會產生一筆資料因此要刪除2
var requestDelete = objectStore.delete(2);
requestDelete.onsuccess = function (event) {
document.getElementById('messageText').innerHTML += "3.4 刪除1筆資料成功!" + '<br /><br />';
};
};
}
刪除資料則只有 2 種,如果要全刪除要透過 Cursor 一筆筆刪除
項目 | 說明 | |
---|---|---|
delete(1) | : | 刪除主鍵 Id 為 1 的資料 |
openCursor() | : | 先取得,然後遍歷每筆資料,執行 .delete(); 方法 |
在 Demo 代碼中,點擊按鈕,刪除 1 筆資料
按下鍵盤F12 開啟開發者模式,可以看到資料已刪除
基於 Demo範例:連結
<button id="insertRowdataButton">4. 刪除資料庫</button><br /><br />
const databaseName = "myDatabase";
//4. 刪除資料庫
function emptyDatabase() {
var deleteRequest = indexedDB.deleteDatabase(databaseName);
deleteRequest.onsuccess = function () {
document.getElementById('messageText').innerHTML += "4. 資料庫已刪除" + '<br /><br />';
};
deleteRequest.onerror = function () {
document.getElementById('messageText').innerHTML += "4. 資料庫無法刪除" + '<br /><br />';
};
}
刪除整個庫相對容易,只要刪除正確名稱的庫[名稱]擊可
在 Demo 代碼中,點擊按鈕,刪除資料庫
按下鍵盤F12 開啟開發者模式,資料庫 “myDatabase” 完全不在了