?寫一個瀏覽器端的數(shù)據(jù)庫 IndexedDB
簡單的入門示例。
頁面大概長這樣:

源碼:
以下代碼包含了一個數(shù)據(jù)庫所有的 CRUD
(增刪改查)操作。
<div>
<button id="js_add_btn">添加書籍</button>
</div>
<div>
<input type="text" name="" id="js_book_id" placeholder="輸入書籍ID"/>
<button id="js_get_by_id_btn">查詢書籍</button>
<button id="js_update_by_id_btn">更新書籍</button>
<button id="js_delete_by_id_btn">刪除書籍</button>
</div>
<div>
<input type="text" name="" id="js_book_author" placeholder="輸入書籍作者查詢"/><button id="js_get_by_author_btn">查詢書籍</button>
</div>
<div>
<button id="js_get_all_btn">查詢所有書籍</button>
</div>
<div id="output"></div>
<script>
(() => {
const dbName = 'MyDB';
const storeName = 'books';
const output = document.getElementById('output')
let db = null;
function setOutputContent(html) {
output.innerText = html;
}
const initDB = () => {
const request = indexedDB.open(dbName);
request.onupgradeneeded = (event) => {
db = event.target.result;
const store = db.createObjectStore(storeName, {
keyPath: 'id',
autoIncrement: true,
});
store.createIndex('author_idx', 'author', { unique: false });
console.log('數(shù)據(jù)庫已創(chuàng)建/升級');
};
request.onsuccess = (event) => {
db = event.target.result;
console.log('數(shù)據(jù)庫已打開');
};
request.onerror = (event) => {
console.error('數(shù)據(jù)庫錯誤:', event.target.error);
setOutputContent('數(shù)據(jù)庫錯誤');
};
};
function wrapper(func) {
return new Promise((resolve, reject) => {
const transaction = db.transaction([storeName], 'readwrite');
const store = transaction.objectStore(storeName);
const res = func(store)
res.onsuccess = () => {
resolve(res.result)
};
res.onerror = (event) => {
reject(event.target.error)
};
});
}
const addBook = async (book) => {
try {
const result = await wrapper((store) => store.add(book))
console.log(result);
setOutputContent(`添加成功!書籍ID: ${result}`);
} catch (error) {
console.error(error);
setOutputContent('添加失敗');
}
};
const getBook = async (id) => {
try {
const book = await wrapper((store) => store.get(id))
if (book) {
console.log('查詢結(jié)果:', book);
setOutputContent(`書名: ${book.title}\n作者: ${book.author}\n價格: $${book.price}`);
} else {
console.log('未找到書籍');
setOutputContent('未找到該書籍');
}
} catch (error) {
console.error(error);
setOutputContent('查詢失敗');
}
};
const getAllBook = async () => {
try {
const book = await wrapper((store) => store.getAll())
if (book) {
console.log('查詢結(jié)果:', book);
setOutputContent(`總數(shù):${book.length}`);
} else {
console.log('未找到書籍');
setOutputContent('未找到該書籍');
}
} catch (error) {
console.error(error);
setOutputContent('查詢失敗');
}
};
const updateBook = async (book) => {
try {
const result = await wrapper((store) => store.put(book))
console.log(result);
setOutputContent(`更新成功!結(jié)果: ${result}`);
} catch (error) {
console.error(error);
setOutputContent('更新失敗');
}
};
const deleteBook = async (id) => {
try {
const result = await wrapper((store) => store.delete(id))
console.log(result);
setOutputContent(`刪除成功!結(jié)果: ${result}`);
} catch (error) {
console.error(error);
setOutputContent('刪除失敗');
}
};
const getByAuthor = async (author) => {
try {
const result = await wrapper((store) => {
const index = store.index("author_idx");
const request = index.getAll(author);
return request;
})
console.log(result);
setOutputContent(`查詢成功!結(jié)果: ${JSON.stringify(result)}`);
} catch (error) {
console.error(error);
setOutputContent('查詢失敗');
}
};
document.getElementById('js_add_btn').onclick = () => {
addBook({
title: 'Web前端入門',
author: '前端路引',
price: (0.99 * Math.random() + 10) .toFixed(2),
});
};
document.getElementById('js_get_by_id_btn').onclick = () => {
const bookId = document.getElementById('js_book_id').value;
getBook(Number(bookId));
};
document.getElementById('js_delete_by_id_btn').onclick = () => {
const bookId = document.getElementById('js_book_id').value;
deleteBook(Number(bookId));
};
document.getElementById('js_update_by_id_btn').onclick = () => {
const bookId = document.getElementById('js_book_id').value;
updateBook({
id: Number(bookId),
title: 'Web前端入門',
author: '公眾號:前端路引',
price: (0.99 * Math.random() + 10) .toFixed(2),
});
};
document.getElementById('js_get_by_author_btn').onclick = () => {
const author = document.getElementById('js_book_author').value
getByAuthor(author);
};
</script>
IndexedDB 大小限制
以下內(nèi)容為 AI 回答:

獲取可用的存儲空間大小
navigator.storage.estimate().then((estimate) => {
console.log(
`已使用:`,
(
(estimate.usage / estimate.quota) * 100
).toFixed(2)
);
console.log(`可使用:`, (estimate.quota / 1024 / 1024).toFixed(2) + "MB");
});
相關(guān)文檔:https://developer.mozilla.org/en-US/docs/Web/API/Storage_API
寫在最后
由于項目中很少使用,所以這 API 給不了太多建議~~
此 API 的應(yīng)用場景還是有的,可以想想下那些超大文件在線處理應(yīng)用,比如 ZIP、PSD、PPT 之類的文件,可以將文件解析后存在 IndexedDB 中,在需要的時候查詢指定數(shù)據(jù)即可,這樣可以節(jié)約很多的解析時間。
只是需要注意,所有存在瀏覽器端的數(shù)據(jù),用戶清空緩存之后都將不復(fù)存在,所以在使用時需做好容錯處理~~
?轉(zhuǎn)自https://www.cnblogs.com/linx/p/19062137
該文章在 2025/9/10 9:08:51 編輯過