介绍
IndexedDB 是一种底层 API,用于在客户端存储大量的结构化数据。目前各浏览器都已支持,兼容性很好。
特点
- IndexedDB 是一个基于 JavaScript 的面向对象数据库,IndexedDB 允许您存储和检索用键索引的对象;
- 可以存储结构化克隆算法支持的任何对象;
- 使用索引实现对数据的高性能搜索;
- IndexedDB API 大部分都是异步的。不会通过返回值提供数据,而是要传递一个回调函数来获取返回值;
- IndexedDB 遵守同源策略。当你在某个域名下操作储存数据的时候,不能操作其他域名下的数据;
- 可以存储文件/二进制大型对象(blobs);
- 在 Web Worker 中可用;
- IndexedDB 是一个事务型数据库系统。
使用
为了获取数据库的访问权限,需要在 window 对象的 indexedDB (en-US) 属性上调用 open() 方法。该方法返回一个 IDBRequest 对象;异步操作通过在 IDBRequest 对象上触发事件来和调用程序进行通信。
具体使用可以看以下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0">
<title>Title</title>
<link href="./favicon.png">
</head>
<body>
</body>
<script>
let dbName = 'helloIndexDB', version = 1, storeName = 'helloStore'
let indexedDB = window.indexedDB
let db
const request = indexedDB.open(dbName, version)
request.onsuccess = function(event) {
db = event.target.result // 数据库对象
console.log('数据库打开成功')
}
request.onerror = function(event) {
console.log('数据库打开报错')
}
request.onupgradeneeded = function(event) {
// 数据库创建或升级的时候会触发
console.log('onupgradeneeded')
db = event.target.result // 数据库对象
let objectStore
if (!db.objectStoreNames.contains(storeName)) {
objectStore = db.createObjectStore(storeName, { keyPath: 'id' }) // 创建表
// objectStore.createIndex('name', 'name', { unique: true }) // 创建索引 可以让你搜索任意字段
}
}
// 添加数据
function addData(db, storeName, data) {
let request = db.transaction([storeName], 'readwrite') // 事务对象 指定表格名称和操作模式("只读"或"读写")
.objectStore(storeName) // 仓库对象
.add(data)
request.onsuccess = function(event) {
console.log('数据写入成功')
}
request.onerror = function(event) {
console.log('数据写入失败')
throw new Error(event.target.error)
}
}
// 根据id获取数据
function getDataByKey(db, storeName, key) {
let transaction = db.transaction([storeName]) // 事务
let objectStore = transaction.objectStore(storeName) // 仓库对象
let request = objectStore.get(key)
request.onerror = function(event) {
console.log('事务失败')
}
request.onsuccess = function(event) {
console.log('主键查询结果: ', request.result)
}
}
// 根据id修改数据
function updateDB(db, storeName, data) {
let request = db.transaction([storeName], 'readwrite') // 事务对象
.objectStore(storeName) // 仓库对象
.put(data)
request.onsuccess = function() {
console.log('数据更新成功')
}
request.onerror = function() {
console.log('数据更新失败')
}
}
// 根据id删除数据
function deleteDB(db, storeName, id) {
let request = db.transaction([storeName], 'readwrite').objectStore(storeName).delete(id)
request.onsuccess = function() {
console.log('数据删除成功')
}
request.onerror = function() {
console.log('数据删除失败')
}
}
// 由于打开indexDB是异步的加个定时器避免 db对象还没获取到值导致 报错
setTimeout(() => {
addData(db, storeName, {
id: new Date().getTime(), // 必须且值唯一
name: '张三',
age: 18,
desc: 'helloWord'
})
getDataByKey(db, storeName, 1638160036008)
updateDB(db, storeName, {id: 1638164880484, desc: '修改的内容'})
deleteDB(db, storeName, 1638164870439)
}, 1000)
</script>
</html>
快捷使用
目前已经有很多已经封装好的第三方库,例如下面几个,大家可以根据需要选用即可:
- localForage:一个简单的 Polyfill,提供了简单的客户端数据存储的值语法。它在后台使用 IndexedDB,并在不支持 IndexedDB 的浏览器中回退到 WebSQL 或 localStorage。
- Dexie.js:IndexedDB 的包装,通过简单的语法,可以更快地进行代码开发。
- ZangoDB:类似 MongoDB 的 IndexedDB 接口,支持 MongoDB 的大多数熟悉的过滤、投影、排序、更新和聚合功能。
- JsStore:一个带有 SQL 语法的 IndexedDB 包装器。