IndexedDB简介
IndexedDB
是一种可以让你在用户浏览器中持久存储数据的方法,对于需要存储大量数据或者离线的web应用都可以考虑使用,相比已经被废弃的WebSQL
,目前来看是IndexedDB未来一种的趋势,并且兼容性比较友好(见下图),如果储存有限的localStorage
(具体大小看各家浏览器支持),不能满足你当前的使用需求,可以考虑使用IndexedDB。
IndexedDB的存储空间取决于硬盘大小和浏览器限制规则,正常情况一定会远远大于localStorage的普遍5M。
另外IndexedDB也遵从同源协议
(same-origin policy),只能访问同域中存储的数据。
目前各大浏览器对于IndexedDB的兼容
*数据来源于 caniuse
IndexedDB主要特点
- 键值对(Key-Value)存储: key具有唯一性,每个key都对应一个value,key可以是对象自身的属性,value能够直接支持复杂的对象结构,另外key可以是二进制对象。
- 支持事物(transaction): IndexedDB是事务模式的数据库,一切操作都发生在事务中,
索引(indexes)
、表(tables)
、指针(cursors)
这些都必须依赖于事物,另外事物本身具有生存周期,只能在生存周期内使用,并且事物只能自动提交,不可以手动操作。 - 异步: IndexedDB的API不通过return语句返回数据,而是需要回调函数来接受数据。执行API时,会向数据库发送一个请求。当操作完成时,数据库会以事件的方式进行通知你,同时事件的类型会告诉你这个操作是否成功。
- 面向对象: indexedDB不是用二维表来表示集合的关系型数据库。
基础操作
1.打开/新建 数据库
indexedDB.open( databaseName, version
)
databaseName: 数据库的名字,如果当前数据库不存在则就会新建,若存在就是打开。
version: 数据库的版本,可省略,若省略,新增时默认为1,打开时默认为当前版本。
现在创建一个新的数据库
window.indexedDB.open('firstDB')
indexedDB.open()会返回一个IDBRequest对象( IDBRequest
对象表示打开的数据库连接,使用open()
和deleteDatabase()
都会返回这个对象,对于数据库的操作都是基于这个对象 )
在执行open操作后我们需要关注IDBRequest
对象的三个事件,success
打开数据库成功、upgradeneeded
数据库升级(当前指定的版本大于实际版本)、error
打开数据库失败。
const dbName = "firstDB"
let messageList = [],
request, db
request = window.indexedDB.open(dbName, 1)
request.onerror = function(event) {
//错误处理
console.error('数据库异常')
}
request.onsuccess = function(event) {
//成功
db = request.result //获取数据库对象
}
request.onupgradeneeded = function(event) {
//版本变更
db = event.target.result //更新数据库对象
}
2.创建对象仓库
在数据库第一次创建的时候,version经历了从无到有的变更,所以会触发onupgradeneeded事件.
需要关注点 1.keyPath主动设置主键,2.createIndex创建索引。
const dbName = "firstDB"
let messageList = [],
request, db
(function() {
'use strict'
if (!('indexedDB' in window)) {
//检查当前浏览器是否支持indexedDB
alert("Your browser doesn't support a stable version of IndexedDB.")
return
}
request = window.indexedDB.open(dbName, 1)
})()
request.onerror = function(event) {
//错误处理
console.error('数据库异常')
}
request.onsuccess = function(event) {
//成功
db = request.result //获取数据库对象
}
request.onupgradeneeded = function(event) {
//版本变更
db = event.target.result //更新数据库对象
let objectStore
if(!db.objectStoreNames.contains('message')) { //检查是否存在message
//不存在则创建message keyPath主动设置主键 { keyPath: 'id' } autoIncrement自动生成主键
//新建索引 参数分别为索引名称、索引所在的属性、配置对象 unique是否允许重复值
objectStore = db.createObjectStore('message',{ autoIncrement: true } )
objectStore.createIndex('time', 'time', { unique: true })
objectStore.createIndex('content', 'content', { unique: false })
}
}
3.插入、读取、遍历、更新、删除数据
插入
需要关注点 创建事物 transaction() 第一个参数 涉及操作的objectStore
第二个参数 操作类型 可省略 默认只读 readonly只读 readwrite读写
function writeData(params) {
//创建事物 第一个参数 涉及的objectStore
//第二个参数 操作类型 可省略 默认只读 readonly只读 readwrite读写
let req = db
.transaction(['message'], 'readwrite')
.objectStore('message')
.add(params)
req.onsuccess = function (event) {
console.info('写入成功')
}
req.onerror = function (event) {
console.error('写入失败: ' + event.srcElement.error.message )
}
}
读取、查找
function readData() {
let transaction = db.transaction(['message']),
objectStore = transaction.objectStore('message'),
req = objectStore.get(1)
req.onsuccess = function() {
if(req.result) {
//读取成功
console.log(req.result)
}
}
req.onerror = function() {
console.error('读取失败')
}
}
function findData(key, value) {
let transaction = db.transaction(['message'], 'readonly'),
store = transaction.objectStore('message'),
index = store.index(key), //对应的key
req = index.get(value) //对应查找的值
req.onsuccess = function(event) { //操作成功
let result = event.target.result
if(result) { //存在结果
console.log(result)
}
}
}
遍历数据、获取全部数据
function traversalData() {
let objectStore = db.transaction('message').objectStore('message')
// openCursor(range, direction) range 对象来限制被检索的项目的范围, direction可以指定你希望进行迭代的方向
objectStore.openCursor().onsuccess = function(event) {
let cursor = event.target.result
if(cursor) {
messageList.push(cursor.value)
cursor.continue() //继续执行
}
else {
console.info('获取完毕')
}
}
}
function readAllData() {
//一次性获取全部数据
let objectStore = db.transaction('message').objectStore('message'),
allRecords = objectStore.getAll()
allRecords.onsuccess = function() {
messageList = allRecords.result
}
}
更新、删除
function updateData(params) {
let req = db
.transaction(['message'], 'readwrite')
.objectStore('message')
.put(params)
req.onsuccess = function(event) {
// 数据已更新
}
req.onerror = function(event) {
// 错误处理
}
}
function deleteData(key) {
let req = db
.transaction(['message'], 'readwrite')
.objectStore('message')
.delete(key)
req.onsuccess = function(event) {
console.info('数据删除成功')
}
}
IDBRequest对象、IDBCursor对象概念强化
IDBRequest对象属性
是由IDBRequest接口返回的事件处理函数的访问结果集,结果集来自对数据库和数据库对象发起的异步查询。我们所有对IndexedDB数据库的读写操作全部都要通过request的方式来实现。request对象初始时不包括任何关于操作结果的信息,当request上的事件触发时,可以通过IDBRequest实例上的事件处理函数访问相关信息。IDBCursor
接口返回一个游标,能够用于遍历数据库中的记录。游标包含一个源,指向需要遍历的索引或者对象存储区。它在所属区间范围内有一个位置,可以根据记录key的顺序递增或递减方向移动。游标使应用程序能够异步处理在游标范围内的所有记录,同时允许在同一时间拥有无数个游标。
提醒
因为数据存在用户本地,当发生用户主动去清除数据,浏览器处于隐私模式退出,用户硬盘容量到达上限,硬盘文件发生损坏等情况下使用都会受影响。