什么是indexedDB
IndexedDB 是一种可以让你在用户的浏览器内持久化存储数据的方法。IndexedDB 为生成 Web Application提供了丰富的查询能力,使我们的应用在在线和离线时都可以正常工作。
IndexedDB 是一个事务型数据库系统,类似于基于 SQL 的 RDBMS。 然而不同的是它使用固定列表,IndexedDB 是一个基于 JavaScript 的面向对象的数据库。 IndexedDB 允许您存储和检索用键索引的对象; 可以存储 structured clone algorithm 支持的任何对象。 您只需要指定数据库模式,打开与数据库的连接,然后检索和更新一系列事务中的数据。
- 浏览器支持:PC端:chromw11+,FF4+,IE10+ 移动端:支持不较弱。
- Web SQL:在移动端的支持比较好,但是W3C已不再维护Web SQL。
存储结构
域名分配独立空间,一个域名下可创建多个数据库,每个DB可以创建多个对象储存空间(表),一个对象存储空间可以存储多个对象数据。
indexedDB的操作
indexedDB的主要操作围绕于:增删改、索引、事务、游标。接下来详细介绍一下关于indexedDB的用法
1. 获取indexedDB1
2
3
4const indexedDB = window.indexedDB
|| window.webkitIndexedDB
|| window.mozIndexedDB
|| window.msIndexedDB;
window.indexedDB对象只有一个open方法,用于打开指定的数据库
2. 打开或创建数据库
1 | DBOpenRequest = window.indexedDB.open(name, version) |
参数为:数据库名和版本号;数据库存在,则打开它;否则创建
DBOpenRequest对象用于处理用户对数据库的操作请求,可以通过它定义操作成功和失败的处理函数。 它有以下三个方法:
- onupgradeneeded:在创建数据库或数据库版本变化时触发,可创建表或索引等
- onsuccess:打开成功时触发(可以获得对象存储空间信息)
- onerror:打开失败时触发
onupgradeneeded事件会在数据库第一次被打开时;打开数据库时指定的版本号高于当前被持久化的数据库版本号。(可通过修改版本号触发该事件),在该事件的回调里面可以对数据库添加表等操作。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17openRequst.onupgradeneeded = (e) => {
console.log('running onupgradeneeded')
// 获得数据库实例对象
db = e.target.result
console.log(`openRequst.onupgradeneeded db.version: ${db.version}`)
// 新建一个表
// 检查这个数据库是否包含这个表/如果不包含 就创建这个表 (参数:keypath主键、是否自增)|
// 哪些字段是索引的、字段是不是唯一的
if (!(db.objectStoreNames.contains(tableName))) {
console.log('need to create the objectStore')
const objectStore = db.createObjectStore(tableName, { keyPath: 'id', autoIncrement: true })
objectStore.createIndex('name', 'name', { unique: false })
objectStore.createIndex('phone', 'phone', { unique: false })
}
}
3. 打开事务
1 | const transaction= db.transaction([tableName],<mode>) |
- readonly:只读
- readwrite:可读写
- verionchange:版本变更
transaction有以下三个方法:
- oncomplete :当事务中的所有操作请求都被处理完成时触发
- onerror:当事务中出现错误时触发,默认的处理方式为回滚事务
- onabort :当事务被终止时触发
4. 从事务中获取存储空间对象objectStore1
const objectStore= transaction.objectStore(tableName)
objectStore对象上的方法:
- add(data):添加数据
- get(value):查询数据
- put(data):更新数据
- delete(value):删除数据
- clear():清空/删除数据库
- index(value):获得索引值
- openCursor():打开游标(用于遍历)
更新数据的时候可以先get获取数据,修改之后再put1
2
3
4
5
6var result = objStore.get("110");
result.onsuccess=function(e){
var student=e.target.result;
student.name='wwww1';
objStore.put(student);
}
result也对应有onsuccess、onerror事件
利用索引查询
1 | const objStore = transaction.objectStore(tabName) |
游标遍历所有
1 | const objectStore = transaction.objectStore(tableName) |
打开游标openCursor()还可以添加两个参数(范围,排序条件),游标遍历符合条件的数据, range可以为null/不写
1 | // 范围 true不包括/false包括 |
5. 关闭数据库
1 | db.close() |
6. 删除数据库
1 | indexedDB.deleteDatabase(dbName) |
总结
1. 打开数据库
indexedDB.open 接收两个参数,分别为数据库名称和版本,返回的是一个 IDBOpenDBRequest 对象。可以以 DOM 事件的方式监听它的 success 和 error 来获取到它的结果。几乎所有对 indexedDB 的异步操作都是这种以事件的方式进行,返回一个拥有结果或错误的 IDBRequest 对象。在这里,open 方法得到的结果是一个 IDBDatabase 的实例。
第二个参数是数据库的版本。版本决定了数据库的模式:存储在里面的 object store 和它们的结构。当第一次通过 open 方法打开数据库时,会触发一个 onupgradeneeded 事件,我们可以也只能在这里设置数据库模式。当数据库已经存在,而我们打开一个更高版本时,同样会触发 onupgradeneeded 事件,用来更新数据库模式。
添加处理方法
我们可以通过监听它的 success, error 以及 upgradeneeded 事件来做相应的操作。
1 | request.onerror = function (event) { |
可以在 success 事件里面拿到 db 对象,这个是后续操作的主体。
错误处理
由于是基于 DOM 事件模式的,所以所有的错误是会冒泡的。也就是说在一个特定 request 的上引发的错误会依次冒泡到事务,然后到 db 对象。
如果为了简化错误处理,可以直接在 db 对象上添加错误处理:
1 | db.onerror = function (e) { |
2. 创建或更新数据库版本
当创建或者增大数据库版本的时候,会触发 onupgradeneeded 事件。在事件内部,可以拿到 db 对象来创建或更新 object store , 具体如下。
1 | request.onupgradeneeded = function (event) { |
3. 构造数据库
indexedDB 是以对象存储(object store)而不是以表结构存储的,一个数据库可以存储任意多个存储对象。每当有一个值存储在 object store 里面,就必须和一个 key 关联起来。有几种提供 key 的方法,取决于 object store 使用 key path 还是 key generator
4. 事务
所有对数据库的操作都是建立在事务 (transaction) 上的,有三种模式(mode):readonly, readewrite, versionchange.
要修改数据库结构的 schema ,必须在 versionchange 模式下。读取和修改对应另外两种模式。
通过 IDBDatabase.transaction 打开一个 transaction, 接收两个参数:storeNames, mode.
加速事务操作:
当定义作用域时(scope), 只定义需要的 object stores. 这样,就可以在不重叠的作用域上并行的执行多个事务。
只有在需要的时候才开启一个 readwrite 事务。因为在重叠的作用域上可以并发执行多个 readonly 事务,但只能有一个 readwrite 事务。