IndexedDB

操作流程

打开数据库

使用IndexedDB 的第一步是打开数据库,使用indexedDB.open()方法

// 第一个参数是字符串,表示数据库的名字。如果指定的数据库不存在,就会新建数据库
// 第二个参数是整数,表示数据库的版本。如果省略,打开已有数据库时,默认为当前版本;新建数据库时,默认为1
var request = window.indexedDB.open(databaseName, version)

indexedDB.open() 方法返回一个IDBRequest对象。这个对象通过三个事件error、success、upgradeneeded,处理打开数据库的操作结果。

  1. error 事件
    error 事件表示打开数据库失败。
request.onerror = function (event) {
	console.log('数据库打开报错')
}
  1. success 事件
    success 事件表示成功打开数据库。
var db
request.onsuccess = function (event) {
	db = request.result
	console.log('数据库打开成功')
}
// 这时,通过request 对象的 result属性拿到数据库对象。
  1. upgradeneeded 事件
    如果指定的版本号,大于数据库的实际版本号,就会发生数据库升级事件 upgradeneeded。
var db
request.onupgradeneeded = function (event) {
	db = event.target.result
}
// 这时通过事件对象的 target.result 属性,拿到数据库实例

新建数据库

新建数据库与打开数据库是同一操作。如果指定的数据库不存在,就会新建。不同之处在于,后续的操作主要在 upgradeneeded 事件的监听函数里面完成,因为这时版本从无到有,所以会触发这个事件。
通常,新建数据库以后,第一件事是新建对象仓库(即新建表)。

// 数据库新建成功后,新增一张叫做person的表格,主键是id
request.onupgradeneeded = function (event) {
	db = event.target.result
	var objectStore = db.createObjectStore('person', { keyPath: 'id'})
}

// 更好的写法是先判断一下,这张表是否存在,如果不存在再新建。
request.onupgradeneeded = function (event) {
	db = event.target.result
	var objectStore
	if (!db.objectStoreNames.contains('person')) {
		objectStore = db.createObjectStore('person', {keyPath: 'id'})
	}
}

主键(key)是默认建立索引的属性。比如,数据记录是 { id: 1, name: '张三’ },那么id 属性可以作为主键。主键也可以指定为下一层对象的属性,比如{foo: {bar: ‘baz’}}的foo.bar也可以指定为主键。
如果数据记录里面没有合适作为主键的属性,那么可以让IndexedDB自动生成主键。

// 指定主键为一个递增的整数
var objectStore = db.createObjectStore('person', {autoIncrement: true})

新建对象仓库以后,下一步可以新建索引。

request.onupgradeneeded = function (event) {
	db = event.target.result
	var objectStore = db.createObjectStore('person', { keyPath: 'id' })
	objectStore.createIndex('name', 'name', {unique:false})
	objectStore.createIndex('email', 'email', {unique:true})
}
// IDBObject.createIndex() 的三个参数分别为索引名称、索引所在的属性、配置对象(说明该属性是否包含重复的值)

新增数据

新增数据指的是向对象仓库写入数据记录。这需要通过事务完成。

// 写入数据需要新建一个事务。新建时必须指定表格名称和操作模式(“只读”或“读写”)。新建事务以后,通过 IDBTransaction.objectStore(name) 方法,拿到IDBObjectStore 对象,再通过表格对象的add()方法,向表格写入一条记录
function add() {
	var request = db.transaction(['person'], 'readwrite')
		.objectStore('person')
		.add({id:1, name: '张三', age: 24, email: '11@qq.com'})
	request.onsuccess = function(event) {
		console.log('数据写入成功')
	}
	request.onerror = function(event) {
		console.log('数据写入失败')
	}
}
add()

读取数据

读取数据也是通过事务完成。

// objectStore.get() 方法用于读取数据,参数是主键的值。
function read() {
	var transaction = db.transaction(['person'])
	var objectStore = transaction.objectStore('person')
	var request = objectStore.get(1)
	request.onerror = function(event) {
		console.log('事务失败')
	}
	request.onsuccess = function(event) {
		if (request.result) {
			console.log('Name:'+request.result.name)
			console.log('Age'+request.result.age)
			console.log('Email'+request.result.email)
		} else {
			console.log('未获得数据记录')
		}
	}
}
read()

遍历数据

遍历数据表格的所有记录,要使用指针对象IDBCursor。

// 新建指针对象的 openCursor() 方法是一个异步操作,所以要监听success 事件
function readAll() {
	var objectStore = db.transaction('person').objectStore('person')
	objectStore.openCursor().onsuccess = function(event) {
		var cursor = event.target.result
		if (cursor) {
			console.log(`Id:${cursor.key}`)
			console.log(`Name${cursor.value.name}`)
			console.log(`Age${cursor.value.age}`)
			console.log(`Email${cursor.value.email}`)
			cursor.continue()
		} else {
			console.log('没有更多数据')
		}
	}
}
readAll()

更新数据

更新数据要使用 IDBObject.put() 方法。

// put() 方法自动更新了主键为1的记录
function update() {
	var request = db.transaction(['person'], 'readwrite')
		.objectStore('person')
		.put({ id: 1, name: '李四', age: 35, email: '11@qq.com' })
	request.onsuccess = function(event) {
		console.log('数据更新成功')
	}
	request.onerror = function(event) {
		console.log('数据更新失败')
	}
}
update()

删除数据

IDBObjectStore.delete() 方法用于删除记录。

function remove() {
	var request = db.transaction(['person'], 'readwrite')
		.objectStore('person')
		.delete(1)
	request.onsuccess = function(event) {
		console.log('数据删除成功')
	}
}

使用索引

索引的意义在于,可以让你搜索任意字段,也就是从任意字段拿到数据记录。
如果不建立索引,默认只能搜索主键(即从主键取值)。

// 假定新建表格的时候,对 name 字段建立了索引。
objectStore.createIndex('name', 'name', { unique: false })

然后从name找到对应的数据记录

var transaction = db.transaction(['person', 'readonly'])
var store = transaction.objectStore('person')
var index = store.index('name')
request.onsuccess = function(e) {
	var result = e.target.result
	if(result) {
		// ...
	} else {
		// ...
	}
}

案例

在这里插入图片描述
在这里插入图片描述

<template>
    <div style="font-size:18px">
        <el-button type="primary" @click="createdDB">新建</el-button>
        <el-button @click="add">新增</el-button>
        <el-button @click="read">读取</el-button>
        <el-button @click="readAll">遍历数据</el-button>
        <el-button @click="update">更新数据</el-button>
        <el-button @click="remove">删除数据</el-button>
    </div>
</template>
<script setup>
var request, db, db_table
function createdDB() {
    request = window.indexedDB.open('person', '1')
    request.onsuccess = function(res) {
        db = res.target.result
        console.log('成功', res)
    }
    request.onerror = function(error) {
        console.log('失败', error)
    }
    request.onupgradeneeded = function(event) {
        db = event.target.result
        var objectStore
        if (!db.objectStoreNames.contains('person')) {
            objectStore = db.createObjectStore('person',{keyPath: 'id'})
        }
        objectStore.createIndex('name', 'name', {unique: false})
        objectStore.createIndex('email', 'email', {unique: true})
    }
}
function add() {
    console.log(db)
    request = db.transaction(['person'], 'readwrite')
        .objectStore('person')
        .add({ id: 1, name: '张三', email: '11@qq.com' })
    request.onsuccess = function(event) {
        console.log('数据写入成功')
    }
    request.onerror = function(event) {
        console.log('数据写入失败')
    }
}
function read() {
    var transaction = db.transaction(['person'])
    var objectStore = transaction.objectStore('person')
    request = objectStore.get(1)
    request.onerror = function(event) {
        console.log('事务失败', event)
    }
    request.onsuccess = function(event) {
        if (request.result) {
            console.log(`name:${request.result.name}`)
            console.log(`email${request.result.email}`)
        } else {
            console.log('未获得数据记录')
        }
    }
}
function readAll() {
    var objectStore = db.transaction('person').objectStore('person')
    objectStore.openCursor().onsuccess = function(event) {
        var cursor = event.target.result
        if (cursor) {
            console.log(`id:${cursor.key}`)
            console.log(`name:${cursor.value.name}`)
            console.log(`email:${cursor.value.email}`)
            cursor.continue()
        } else {
            console.log('没有更多数据')
        }
    }
}
function update() {
    request = db.transaction(['person'], 'readwrite')
        .objectStore('person')
        .put({id: 1, name: 'haha', email: 'haha@qq.com'})
    request.onsuccess = function(event) {
        console.log('数据更新成功')
    }
    request.onerror = function(event) {
        console.log('数据更新失败')
    }
}
function remove() {
    request = db.transaction(['person'], 'readwrite')
        .objectStore('person')
        .delete(1)
    request.onsuccess = function(event) {
        console.log('数据删除成功')
    }
}
</script>

indexedDB对象

indexedDB.open()

indexedDB.open() 方法用于打开数据库。这是一个异步操作,但是会立刻返回一个IDBOpenDBRequest 对象。

var openRequest = window.indexedDB.open('test', 1)
// 打开一个名为test,版本为1的数据库。如果该数据库不存在,则会新建该数据库。

// open() 方法的
// 第一个参数是数据库名称,格式为字符串,不可省略;
// 第二参数是数据库版本,是一个大于0的正整数(0报错),如果该参数大于当前版本,会触发数据库升级。第二个参数可省略,如果数据已存在,将打开当前版本的数据库;如果数据库不存在,将创建版本的数据库,默认版本为1.

打开数据库是异步操作,通过各种事件通知客户端。四种事件:

  • success:打开成功
  • error:打开失败
  • upgradeneeded:第一次打开该数据库,或者数据库版本发生变化
  • blocked:上一次的数据库连接还未关闭
    第一次打开数据库时,会先触发 upgradeneeded 事件,然后触发 success 事件。
    根据不同的需要,对上面4种事件监听函数。
// open() 方法返回的是一个对象(IDBOpenDBRequest),监听函数就定义在这个对象上面。
// success 事件发生后,从openRequest.result 属性可以拿到已经打开的 IndexedDB 数据库对象。
var openRequest = indexedDB.open('test', 1)
var db

openRequest.onupgradeneeded = function(e) {
	console.log('upgrading...')
}

openRequest.onsuccess = function(e) {
	console.log('success')
	db = openRequest.result
}

openRequest.onerror = function(e) {
	console.log('Error')
	console.log(e)
}

indexedDB.deleteDatabase()

indexedDB.deleteDatabase() 方法用于删除一个数据库,参数为数据库的名字。返回一个 IDBOpenDBRequest 对象,然后对数据库执行异步删除。删除操作的结果会通过事件通知,IDBOpenDBRequest 对象可以监听以下事件。

  • success:删除成功
  • error:删除报错
// 调用 deleteDatabase() 方法以后,当前数据库的其他已经打开的连接都会接收到 versionchange 事件。
// 注意:删除不能存在的数据库不会报错。
var DBDeleteRequest = window.indexedDB.deleteDatabase('demo')

DBDeleteRequest.onerror = function(event) {
	console.log('Error')
}

DBDeleteRequest.onsuccess = function(event) {
	console.log('success')
}

indexedDB.cmp()

indexedDB.cmp() 方法比较两个值是否为 indexedDB 的相同的主键。返回一个整数,表示比较的结果:0表示相同,1表示第一个主键大于第二个主键,-1表示第一个主键小于第二个主键。

window.indexedDB.cmp(1, 2)  // -1

注意:此方法不能用来比较任意的JavaScript值。如果参数是布尔值或对象,它会报错。

window.indexedDB.cmp(1, true)  // 报错
window.indexedDB.cmp({}, {})  // 报错

IDBRequest 对象

IDBRequest 对象表示打开的数据库连接,indexedDB.open() 方法和 indexedDB.deleteDatabase() 方法会返回这个对象。数据库的操作都是通过这个对象完成的。
这个对象的所有错做都是异步操作,要通过readyState属性判断是否完成,如果为 peding 就表示操作正在进行,如果为 done 就表示操作完成,可能成功有可能失败。
操作完成后,触发 success 事件或 error 事件,这时可以通过 result 属性和 error 属性拿到操作结果。如果在pending 阶段,就去读取这两个属性,会报错。
IDBRequest对象有以下属性。

  • IDBRequest.readyState:等于 pending 表示操作正在进行,等于 done 表示操作正在完成。
  • IDBRequest.result:返回请求的结果。如果请求失败、结果不可用,读取该属性会报错。
  • IDBRequest.error:请求失败时,返回错误对象。
  • IDBRequest.source:返回请求的来源(比如索引对象或 ObjectStore )。
  • IDBRequest.transaction:返回当前请求正在进行的事务,如果不包含事务,返回 null。
  • IDBRequest.onsuccess:指定 success 事件的监听函数。
  • IDBRequest.onerror:指定 error 事件的监听函数。
    IDBOpenDBRequest 对象继承了 IDBRequest 对象,提供了两个额外的事件监听属性。
  • IDBOpenDBRequest.onblocked:指定 blocked 事件( upgradeneeded 事件触发时,数据库仍然在使用)监听的函数。
  • IDBOpenDBRequest.onupgradeneeded: upgradeneeded 事件的监听函数。

IDBDatabase对象

打开数据成功以后,可以从 IDBOpenDBRequest 对象的 result 属性上面,拿到一个 IDBDatabase 对象,它表示连接的数据库。后面对数据库的操作,都通过这个对象完成。

var db
var DBOpenRequest = window.indexedDB.open('demo', 1)

DBOpenRequest.onerror = function(event) {
	console.log('error')
}

DBOpenRequest.onsuccess = function(event) {
	db = DBOpenRequest.result
	// ...
}

属性
IDBDatabase 对象有一下属性:

  • IDBDatabase.name:字符串,数据库名称。
  • IDBDatabase.version:整数,数据库版本。数据库第一次创建时,该属性为空字符串。
  • IDBDatabase.objectStoreNames:DOMStringList 对象(字符串的集合),包含当前数据的所有 object store 的名字。
  • IDBDatabase.onabort:指定 abort 事件(事务中止)的监听函数。
  • IDBDatabase.onclose:指定 close 事件(数据库意外关闭)的监听函数。
  • IDBDatabase.onerror:指定 error 事件(访问数据库失败)的监听函数。
  • IDBDatabase.onversionchange:数据库版本变化时触发(发生upgradeneeded 事件,或调用 indexedDB.deleteDatabase())。
    下面是 objectStoreNames 属性的例子。该属性返回一个DOMStringList 对象,包含当前数据库所有对象仓库的名称(即表名),可以使用 DOMStringList 对象的 contains 方法,检查数据库是否包含某个对象仓库。
// 先判断某个对象仓库是否存在,如果不存在就创建该对象仓库。
if (!db.objectStoreNames.contains('firstOS')) {
	db.createObjectStore('firstOS')
}

方法
IDBDatabase 对象有以下方法。

  • IDBDatabase.close():关闭数据库连接,实际会等所有事务完成后再关闭。
  • IDBDatabase.createObjectStore():创建存放数据的对象仓库,类似于传统关系型数据库的表格。返回一个IDBOjectStore对象。该方法只能在 versionchange 事件监听函数中调用。
  • IDBDatabase.deleteObjectStore():删除指定的对象仓库。该方法只能在 versionchange 事件监听函数中调用。
  • IDBDatabase.transaction():返回一个 IDBTransaction 事务对象。

下面是 createObjectStore() 方法的例子。

// 创建了一个名为 items 的对象仓库,如果该对象仓库已经存在,就会抛出一个错误。为避免该错误,可采用 objectStoreNames 属性,检查已有哪些对象仓库。
var request = window.indexedDB.open('demo', 2)

request.onupgradeneeded = function(event) {
	var db = event.target.result
	
	db.onerror = function(event) {
		console.log('error')
	}

	var objectStore = db.createObjectStore('items')
	
	// ...
}

createObjectStore() 方法还可以接受第二个对象参数,用来设置对象仓库的属性。

// keyPath 属性表示主键(由于主键的值不能重复,所以上例存入之前,必须保证数据的 email 属性值都是不一样的),默认值为 null;autoIncrement 属性表示,是否使用自动递增的整数作为主键(第一个数据记录为1,第二个数据记录为2,以此类推),默认为false。一般来说, keyPath 和 autoIncrement 属性只要使用一个就够了,如果两个同时使用,表示主键为递增的整数,且对象不得缺少 keyPath 指定的属性。
db.createOjbectStore('test', { keyPath: 'email' })
db.createObjectStore('test2', { autoIncrement: true }

deleteObjectStore() 方法的例子

var dbName = 'sampleDB'
var dbVersion = 2
var request = indexedDB.open(dbName, dbVersion)

request.onupgradeneeded = function(e) {
	var db = request.result
	if (e.oldVersion < 1) {
		db.createObjectStore('store1')
	}
	if (e.oldVersion < 2) {
		db.deleteObjectStore('store1')
		db.createObjectStore('store2')
	}
	// ...
}

transaction() 方法的例子,该方法用于创建一个数据库事务,返回一个 IDBTransaction 对象。向数据库添加数据之前,必须先创建数据库事务。

var t = db.transaction(['items'], 'readwrite')

transaction() 方法接受两个参数:第一个参数是一个数组,里面是所涉及的对象仓库,通常是只有一个;第二个参数是一个表示操作类型的字符串。目前,操作类型只有两种:readonly(只读)和 readwrite(读写)。添加数据使用 readwrite,读取数据使用 readonly。第二个参数是可选的,省略时默认为 readonly 模式。

IDBObjectStore 对象

IDBObjectStore 对象对应一个对象仓库(object store)。
IDBDatabase.createObjectStore() 方法返回的就是一个 IDBObjectStore 对象。
IDBDatabase 对象的 transaction() 返回一个事务对象,该对象的 objectStore() 方法返回 IDBObjectStore 对象,因此可以采用下面的链式写法。

db.transaction(['test'], 'readonly')
  .objectStore('test')
  .get(X)
  .onsuccess = function (e) {}

属性

IDBObjectStore 对象有以下属性。

  • IDBObjectStore.indexNames:返回一个类似数组的对象(DOMStringList),包含了当前对象仓库的所有索引。
  • IDBObjectStore.keyPath:返回当前对象仓库的主键。
  • IDBObjectStore.name:返回当前对象仓库的名称。
  • IDBObjectStore.transaction:返回当前对象仓库所属的事务对象。
  • IDBObjectStore.autoIncrement:布尔值,表示主键是否会自动递增。

方法

IDBObjectStore 对象有以下方法。

(1)IDBObjectStore.add()

IDBObjectStore.add() 用于向对象仓库添加数据,返回一个 IDBRequest 对象。该方法只用于添加数据,如果主键相同会报错,因此更新数据必须使用 put() 方法。

objectStore.add(value, key)

该方法接受两个参数,第一个参数是键值,第二个参数是主键,该参数可选,如果省略,默认为 null。
创建事务以后,就可以获取对象仓库,然后使用 add() 方法往里面添加数据了。

var db
var DBOpenRequest = window.indexedDB.open('demo', 1)

DBOpenRequest.onsuccess = function(event) {
	db = DBOpenRequest.result
	var transaction = db.transaction(['items'], 'readwrite')
	
	transaction.oncomplete = function(event) {
		console.log('transaction success')
	}
	
	transaction.onerror = function(event) {
		console.log('transaction error')
	}

	var objectStore = transaction.objectStore('item1')
	var objectStoreRequest = objectStore.add({foo: 1})

	objectStoreRequest.onsuccess = function (event) {
		console.log('add data success')
	}
}

(2)IDBObjectStore.put()

IDBObjectStore.put() 方法用于更新某个主键对应的数据记录,如果对应的键值不存在,则插入一条新的记录。该方法返回一个 IDBRequest 对象。

objectStore.put(item, key)

该方法接受两个参数,第一个参数为新数据,第二个参数为主键,该参数可选,且只在自动递增时才有必要提供,因为那时主键不包含在数据值里面。

(3)IDBObjectStore.clear()

IDBObjectStore.clear() 删除当前对象仓库的所有记录。该方法返回一个 IDBRequest 对象。

// 该方法不需要参数。
objectStore.clear()

(4)IDBObjectStore.delete()

IDBObjectStore.delete() 方法用于删除指定主键的记录。该方法返回一个 IDBRequest 对象。

// 该方法的参数为主键的值
objectStore.delete(key)

(5)IDBObjectStore.count()

IDBObjectStore.count() 方法用于计算记录的数量。该方法返回一个 IDRequest 对象。

// 不带参数时,该方法返回当前对象仓库的所有记录数量。如果主键或 IDBKeyRange 对象作为参数,则返回对应的记录数据
objectStore.count(key)

(6)IDBObjectStore.getKey()

IDBObjectStore.getKey() 用于获取主键。该方法返回一个 IDBRequest 对象。

// 该方法的参数可以是主键值或 IDBKeyRange 对象
objectStore.getKey(key)

(7)IDBObjectStore.get()

IDBObjectStore.get() 用于获取主键对应的数据记录。该方法返回一个 IDBRequest 对象。

objectStore.get(key)

(8)IDBObjectStore.getAll()

IDBObjectStore.getAll() 用于获取对象仓库的记录。该方法返回一个 IDBRequest 对象。

// 获取所有记录
objectStore.getAll()

// 获取所有符合指定主键或 IDBKeyRange 的记录
objectStore.getAll(query)

// 指定获取记录的数量
objectStore.getAll(query, count)

(9)IDBObjectStore.getAllKeys()

IDBObjectStore.getAllKeys() 用于获取所有符合条件的主键。该方法返回一个 IDBRequest 对象。

// 获取所有记录的主键
objectStore.getAllKeys()

// 获取所有符合条件的主键
objectStore.getAllKeys(query)

// 指定获取主键的数量
objectStore.getAllKeys(query, count)

IDBObjectStore.index()

IDBObjectStore.index() 方法返回指定名称的索引对象 IDBIndex。

objectStore.index(name)

有了索引以后,就可以针对索引所在的属性读取数据。

var t = db.transaction(['people'], 'readonly')
var store = t.objectStore('people')
var index = store.index('name')

var request = index.get('foo')
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值