大家好,又见面了,我是你们的朋友全栈君。
indexedDB介绍
indexedDB是一个前端数据持久化解决方案(即前端缓存),由浏览器实现。
一组相关业务数据的存储集合。
window.indexedDB.open(dbName, version)示例:
const dbRequest = window.indexedDB.open('demo', 1);
onpen() 方法说明:
request 实例。【因为indexedDB 是异步的,所以它所有的操作都必须建立一个请求(request),请求的结果将被封装在request实例中返回】
request 实例。
某项业务的数据集合,有三种类型
keyPathkeyPath,会报错keyPathkeyPathif (!db.objectStoreNames.contains(tableName)){
db.createObjectStore(tableName, options)
}示例:
const dbRequest = window.indexedDB.open('demo', 2);
dbRequest.onupgradeneeded = (e) => {
const db = e.target.result;
if (!db.objectStoreNames.contains('objectStore')) {
db.createObjectStore('objectStore', {
keyPath: 'id' });
}
if (!db.objectStoreNames.contains('objectStoreCopy')) {
db.createObjectStore('objectStoreCopy', {
keyPath: 'id' });
}
if (!db.objectStoreNames.contains('notObjectStore')) {
db.createObjectStore('notObjectStore', {
autoIncrement: true });
}
if (!db.objectStoreNames.contains('mixStore')) {
db.createObjectStore('mixStore', {
autoIncrement: true, keyPath: 'id'});
}
}
createObjectStore 方法说明:
db-request的onupgradeneeded事件中进行,而onupgradeneeded 事件只在数据库版本升级时触发,所以我们这里版本号升级了。对于库的版本说明,见下节。
options参数有两个可设置属性,见 5.记录 一节
keyPath
autoIncrement
上图所示是设置了keyPath的表,我们看到在Key后面有一个括号里,标识了它的Key path
下图则是设置了autoIncrement的表,我们看到它只有Key:


keyPath。在值对象中,获取一个节点值的属性链式方法的字符串表达keyPath,只有自增的keydb.transaction(objectStoresArray, readWriteMode)示例:
const request = window.indexedDB.open('demo', 2);
request.onsuccess = (e) => {
const db = e.target.result;
let transcation =
db.transaction(['objectStore', 'objectStoreCopy', 'notObjectStore', 'mixStore'], 'readwrite');
}transaction()方法说明:
db-request的成功回调onsuccess方法中创建,另注意:数据库实例db 需要从成功回调的结果的target.result中获取。
objectStoresArray, 一个数组,包含了当前事务中要操作的所有表的名称
readWriteMode: 本次操作是只读操作还是读写操作
readonly: 只读readwrite:读写transaction.objectStore(tableName)示例:
// 省略连接数据库和读取数据库实例的过程,以下代码在dbRquest的回调中进行
let transcation =
db
.transaction(['objectStore', 'objectStoreCopy', 'notObjectStore'], 'readonly');
let os = transcation.objectStore('objectStore');
let osc = transcation.objectStore('objectStoreCopy');
let nos = transcation.objectStore('notObjectStore');
let ms = transcation.objectStore('mixStore');objectStore()方法说明:
transaction()方法的第一个参数中指定,否则将会报错,比如最后一行读取的就是一个没有指定的表,将会报以下错误:


objectStore.add(object)示例:
const request = window.indexedDB.open('demo', 2);
request.onsuccess = (e) => {
const db = e.target.result;
let transcation =
db
.transaction(['objectStore', 'objectStoreCopy', 'notObjectStore','mixStore'], 'readwrite');
let os = transcation.objectStore('objectStore');
let osc = transcation.objectStore('objectStoreCopy');
let nos = transcation.objectStore('notObjectStore');
let ms = transcation.objectStore('mixStore');
// 对象型仓库,keyPath为对象的一个属性
os.add({
id: 1,
name: '张三',
sex: '男',
other:{
age: 18
}
});
// 非对象型仓库,存入几个非对象数据
// Date类型
const date = new Date();
// Blob类型
const s = "<div>Hello World!!</div>";
const blob = new Blob([s], {
type: 'text/xml'});
// ArrayBuffer
const buffer = new ArrayBuffer(8);
// 数组
const arr = [1,2,3];
// 图像数据
const imageData = new ImageData(100, 100);
// 文件
const file = new File(["foo"], "foo.txt", {
type: "text/plain",
});
nos.add(date);
nos.add(blob);
nos.add(buffer);
nos.add(arr);
nos.add(imageData);
nos.add(file);
// 混合型仓库
ms.add({
id: 1,
name: '张三',
sex: '男',
other:{
age: 18
}
});
ms.add(blob);
ms.add(buffer);
ms.add(arr);
// 对象型仓库,keyPath 不是对象的属性,将添加失败
osc.add({
name: '张三',
sex: '男',
other:{
age: 18
}
});看一下添加结果:




当我们试图插入一条keyPath与已有记录的keyPath相同的记录时,将会失败,如果同一张表还有其他操作,将随事务回滚也一起失败。
let transcation =
db
.transaction(['objectStore'], 'readwrite');
let os = transcation.objectStore('objectStore');
// 试图插入一个主键不同的数据
let rs3 = os.add({
id: 2,
name: '张四',
sex: '女',
other:{
age: 18
}
});
rs3.onsuccess = e => {
console.log('rs3成功');
};
rs3.onerror = e => {
console.log('rs3失败');
console.log(e.target.error.message);
};
// 视图插入一个主键相同的数据
let rs = os.add({
id: 1,
name: '张四',
sex: '女',
other:{
age: 18
}
});
rs.onsuccess = e => {
console.log('rs成功');
};
rs.onerror = e => {
console.log('rs失败');
console.log(e.target.error.message);
};
我们看到,这里试图插入一个与已有记录keyPath不同的记录,实际上显示成功了,而尝试插入一条与已有记录keyPath 相同的记录时,提示失败了,然后我们看数据库:

虽然id为2的数据提示插入成功了,但是数据里并没有,说明因为它之后进行的rs失败了,所以导致事务回滚了,它本来成功的操作也被回滚,最终数据没有插入进去。
objectStore.put(object)示例:
// 更新一个记录
let rs2 = os.put({
id: 1,
name: '张四',
sex: '女',
other:{
age: 18
}
});
rs2.onsuccess = e => {
console.log('rs2成功');
};
rs2.onerror = e => {
console.log('rs2失败');
console.log(e.target.error.message);
};我们将之前添加到对象型仓库里id为1的记录的名字由张三改为张四,性别由男改为女,看看结果:

可以看到,更新成功了
更新一条keyPath不存在的数据:
let rs4 = os.put({
id: 2,
name: '张三三',
sex: '男',
other:{
age: 18
}
});
rs4.onsuccess = e => {
console.log('rs4成功');
};
rs4.onerror = e => {
console.log('rs4失败');
console.log(e.target.error.message);
};
可以看到,更新操作如果更新的是一条keyPath不存在的记录,它将按照新增add() 来处理。
所以:
我们强烈建议,添加数据都使用put()操作
objectStore.get(KeyPathValue)示例:
const db = e.target.result;
let transcation =
db
.transaction(['objectStore'], 'readwrite');
let os = transcation.objectStore('objectStore');
// 先插入几条数据
os.put({
id: 3,
name: '王五',
sex: '男',
other:{
age: 16
}
});
os.put({
id: 4,
name: '王六',
sex: '女',
other:{
age: 16
}
});
os.put({
id: 5,
name: '鬼脚七',
sex: '男',
other:{
age: 16
}
});
let rs = os.get(5);
rs.onsuccess = e => {
console.log('rs成功');
console.log(e.target.result);
};
rs.onerror = e => {
console.log('rs失败');
console.log(e.target.error.message);
};看看结果


objectStore.delete(keyPathValue)示例
let transcation =
db
.transaction(['objectStore'], 'readwrite');
let os = transcation.objectStore('objectStore');
let rs = os.delete(3);
rs.onsuccess = e => {
console.log('rs成功');
console.log(e.target.result);
};
rs.onerror = e => {
console.log('rs失败');
console.log(e.target.error.message);
};

objectStore.createIndex(indexName, Path, options)参数说明
indexName: 索引名称
Path: 索引在对象中的路径
options: 可选参数对象
unique。如果为true,索引将不允许单个键的值重复。multiEntry 。如果为 true,则当 Path 解析为数组时,索引将为每个数组元素在索引中添加一个条目。 如果为 false,它将添加一个包含数组的条目。locale。目前只有Firefox(43+)支持,这允许您为索引指定区域设置示例:
const request = window.indexedDB.open('demo', 3);
request.onupgradeneeded = (e) => {
const db = e.target.result
let os;
if (!db.objectStoreNames.contains('objectStore')) {
os = db.createObjectStore('objectStore', {
keyPath: 'id' });
} else {
os = e.target.transaction.objectStore('objectStore');
}
os.createIndex('sex', 'sex', {
unique: false });
os.createIndex('age', 'other.age', {
unique: false });
os.createIndex('name', 'name', {
unique: true });
}onupgradeneeded 中进行,这表示要对数据库升级,所以我们又升了版本号。看看结果:




objectStore.index(indexName)示例:
const request = window.indexedDB.open('demo', 3);
request.onsuccess = (e) => {
const db = e.target.result;
let transcation =
db
.transaction(['objectStore'], 'readwrite');
let os = transcation.objectStore('objectStore');
let objIndexName = os.index('name');
let objIndexAge = os.index('age');
let objIndexSex = os.index('sex');
let rs1 = objIndexName.get('张三');
rs1.onsuccess = e => {
console.log('rs1查询成功');
console.log(e.target.result);
}
rs1.onerror = e => {
console.log('rs1查询失败');
console.log(e.target.error.message);
}
let rs2 = objIndexAge.get(16);
rs2.onsuccess = e => {
console.log('rs2查询成功');
console.log(e.target.result);
}
rs2.onerror = e => {
console.log('rs2查询失败');
console.log(e.target.error.message);
}
let rs3 = objIndexSex.get('男');
rs3.onsuccess = e => {
console.log('rs3查询成功');
console.log(e.target.result);
}
rs3.onerror = e => {
console.log('rs3查询失败');
console.log(e.target.error.message);
}
}看看结果:

可以看到,上例中我们以索引名称查询,
name为张三的用户,所以返回为undefinedage与sex来查询,都查到了相应的结果age为16和sex为男的记录都不止一条get()操作只返回符合条件的第一条记录,要获得所有符合条件的记录,就需要下面要将的游标。一个可以遍历整个表的接口。
index.openCursor()cursor.continue();示例:
const request = window.indexedDB.open('demo', 3);
request.onsuccess = (e) => {
const db = e.target.result;
let transcation =
db
.transaction(['objectStore'], 'readwrite');
let os = transcation.objectStore('objectStore');
let objIndexSex = os.index('sex');
let rs1 = objIndexSex.openCursor();
let results = []; // 用来存放这个表中所有记录,它的声明必须放在 onsuccess 回调函数的外部,因为该回调函数会在遍历过程中反复执行
let resultsMan = []; // 用来存放男人
rs1.onsuccess = e => {
console.log('rs1查询成功');
let cursor = e.target.result;
if (cursor) {
results.push(cursor.value);
if (cursor.value.sex === '男') {
resultsMan.push(cursor.value);
}
cursor.continue();
} else {
console.log(results);
console.log(resultsMan);
}
}
rs1.onerror = e => {
console.log('rs1查询失败');
console.log(e.target.error.message);
}
}看看结果:

objectStore.deleteIndex(indexName)示例:
const request = window.indexedDB.open('demo', 4);
request.onupgradeneeded = (e) => {
const db = e.target.result
let os;
if (!db.objectStoreNames.contains('objectStore')) {
os = db.createObjectStore('objectStore', {
keyPath: 'id' });
} else {
os = e.target.transaction.objectStore('objectStore');
}
os.deleteIndex('sex');
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/211081.html原文链接:https://javaforall.cn