indexDB(对象接口、异步、支持事务、同源限制、二进制存储、永久存储、打开数据库、初始化数据库、通过事务对数据库进行增删改查操作)
目录简介对象接口特点键值对储存异步支持事务同源限制储存空间大支持二进制储存永久存在使用打开数据库(创建)var request = window.indexedDB.open(databaseName, version)error 事件success 事件upgradeneeded 事件初始化数据库IDBDatabase.createObjectStore(formName, { keyPath:
目录
var request = window.indexedDB.open(databaseName, version)
IDBDatabase.createObjectStore(formName, { keyPath: ID })
IDBObjectStore.createIndex(indeName,property,{unique:boolean})
IDBDatabase.transaction([formName],'readwrite').objectStore(formName).add(obj)
IDBDatabase.transaction([formName]).objectStore(formName).get(primaryValue)
IDBDatabase.transaction([formName]).objectStore(formName).objectStore.put(obj)
IDBDatabase.transaction([formName]).objectStore(formName).objectStore.delete(primaryValue)
简介
IndexedDB 是浏览器提供的本地数据库,它可以被网页脚本创建和操作。IndexedDB 允许储存大量数据,提供查找接口,还能建立索引。IndexedDB 不属于关系型数据库(不支持 SQL 查询语句),更接近 NoSQL 数据库。
可以在网页中F12打开控制台后点击应用并在存储中查看。例如下图:
对象接口
IndexedDB 是一个比较复杂的 API,涉及不少概念。它把不同的实体,抽象成一个个对象接口。学习这个 API,就是学习它的各种对象接口。
下面是它的所有对象。
- 操作请求:IDBRequest 对象(open函数返回的对象)
- 数据库:IDBDatabase 对象(IDBRequest上的result属性)
- 对象仓库:IDBObjectStore 对象(表名)
- 索引: IDBIndex 对象(建立后可以通过get方法查找对应数据(未建立前只能通过主键查找))
- 事务: IDBTransaction 对象(新建数据库后只能通过事务对象上的方法对数据库进行增删改查)
- 指针: IDBCursor 对象(用于遍历数据库)
- 主键集合:IDBKeyRange 对象
特点
键值对储存
IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以"键值对"的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。
异步
IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。
支持事务
IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。
同源限制
IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
储存空间大
IndexedDB 的储存空间比 LocalStorage (2.5MB~10MB)大得多,一般来说不少于 250MB,甚至没有上限。
支持二进制储存
IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。
永久存在
和localStorage一样,只有手动删除时才会消失。
使用
打开数据库(创建)
var request = window.indexedDB.open(databaseName, version)
该方法返回一个 IDBRequest 对象。这个对象通过三种事件error
、success
、upgradeneeded
,处理打开数据库的操作结果。
参数:databaseName是字符串,表示数据库的名字。如果指定的数据库不存在,就会新建数据库。version是整数,表示数据库的版本。如果省略,打开已有数据库时,不写默认为当前版本,如果版本低于已有数据库版本,会触发error事件;新建数据库时,默认为1
。
如图下面为一个IDBRequest对象,只有readyState状态为done时才会触发三种事件方法,当为pending时,任何事件方法都不会触发。result属性对应的是IDBDatabase对象,该对象的name对应databaseName字符串,version对应。
error 事件
error
事件表示打开数据库失败。
request.onerror = function (event) {
console.log('数据库打开报错');
};
success 事件
success
事件表示成功打开数据库。
var db;
request.onsuccess = function (event) {
db = request.result;
console.log('数据库打开成功');
};
这时,通过request
对象的result
属性拿到数据库对象。
upgradeneeded 事件
如果指定的版本号,大于数据库的实际版本号,就会发生数据库升级事件upgradeneeded
。
创建数据库也是升级事件(版本从无到有),先触发升级事件再触发成功打开数据库事件。
var db;
request.onupgradeneeded = function (event) {
db = event.target.result;
}
这时通过事件对象的target.result
属性,拿到数据库实例。
初始化数据库
新建对象仓库(即新建表)。一般在upgradeneeded事件里通过IDBDatabase对象的方法新建表,表中新建索引,最后放入数据。
IDBDatabase.createObjectStore(formName, { keyPath: ID })
新建表并设置主键,该方法返回IDBObjectStore对象,表示新建一个名为formName的表,其中主键名为ID。
参数:formName、ID为字符串。
下面代码:对这张表格是否存在进行了判断,如果不存在再新建。
request.onupgradeneeded = function (event) {
db = event.target.result;
var objectStore;
if (!db.objectStoreNames.contains('person')) {
objectStore = db.createObjectStore('person', { keyPath: 'id' });
}
}
注意:主键在数据中是不允许重名。
如果数据记录里面没有合适作为主键的属性,那么可以让 IndexedDB 自动生成主键。将函数中第二个参数改为{ autoIncrement: true },表示主键为一个递增的整数。
IDBObjectStore.createIndex(indeName,property,{unique:boolean})
新建索引。
参数:indexName为字符串表示数据库中的索引名称,property为字符串表示索引所在上的属性(对应新增对象数据时,取的属性值)、第三个参数是配置对象(说明该属性是否包含重复的值)。索引名称和索引所在的属性名一般相同。
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 });
}
IDBObjectStore.add(obj)
新增一条数据,用于初始化数据。在外部新增数据要通过事务拿到对象仓库才能调用add方法。
参数:obj为一个对象,该对象的属性名和上一个方法中的property属性应该对应,这样才能添加进入值,且还要注意主键和一些属性unique为true的属性的值时不能重复的,如果重复在已有数据库添加数据时只会导致添加失败,但在新建数据库时即在onupgradeneeded事件使用中会导致新建数据库失败。
//onupgradeneeded中添加数据
var db
request.onupgradeneeded = function (event) {
db = event.target.result;
var objectStore = db.createObjectStore('person', { keyPath: 'id' });
objectStore.createIndex('name1', 'name', { unique: false });
objectStore.createIndex('email1', 'email', { unique: true });
objectStore.add({id:'1',name:'2',email:'3'})
objectStore.add({id:'2',name:'3',email:'4'})
}
事务操作
新增数据
这里的新增数据和初始化数据中的不同,不能直接拿到对象仓库。所以需要通过事务完成。
IDBDatabase.transaction([formName],'readwrite').objectStore(formName).add(obj)
写入数据需要新建一个事务。新建时必须指定表格名称和操作模式("只读"、"读写")。新建事务以后,通过IDBTransaction.objectStore(name)
方法,拿到 IDBObjectStore 对象,再通过表格对象的add()
方法,向表格写入一条记录。
参数:formName为字符串是需要插入数据库的表名,obj为一个对象,是插入的数据,该对象的属性名和索引中属性应该对应,
注意:写入操作是一个异步操作,通过监听连接对象的success
事件和error
事件,了解是否写入成功。每次都需要重新使用一遍事务即每次都需要使用重新使用transaction方法(即每次都要.transaction([formName],'readwrite').objectStore(formName).add(obj)用一遍)
下面封装了一个向指定数据库中添加数据的函数。databseName为需要打开的数据库名,formName为写入数据库的表名,dataArr为写入的数据,是一个数组,每位都是一个对象。
function add(databaseName,formName,dataArr) {
let request = window.indexedDB.open(name)
let db=request.result
for(let i=0;i<dataArr.length;i++){
let res = db.transaction([formName], 'readwrite')
.objectStore(formName)
.add(dataArr[i])
}
request.onsuccess = function (event) {
console.log('数据写入成功')
}
request.onerror = function (event) {
console.log('数据写入失败')
}
}
读取数据
IDBDatabase.transaction([formName]).objectStore(formName).get(primaryValue)
读取数据也是同样也是通过事务完成。
参数:formName表示同上,primaryValue为字符串,会在数据库中查找到主键值为primaryValue的那一条数据返回到对象的result属性上。
下面是封装的函数打开指定数据库的指定表,并打印对应主键为primaryValue的那一条数据。
function read(databaseName,formName,primaryValue) {
let request = window.indexedDB.open(name)
let db=request.result
let transaction = db.transaction([formName]);
let objectStore = transaction.objectStore(formName);
let res = objectStore.get(primaryValue);
res.onerror = function(event) {
console.log('事务失败');
};
res.onsuccess = function( event) {
if (res.result) {
console.log('id: ' + res.result.id);
console.log('Name: ' + res.result.name);
console.log('Email: ' + res.result.email);
} else {
console.log('未获得数据记录');
}
};
}
遍历数据
遍历数据表格的所有记录,要使用指针对象 IDBCursor。
IDBDatabase.transaction([formName]).objectStore(formName).objectStore.openCursor().onsuccess = function (event) {}
新建指针对象的openCursor()
方法是一个异步操作,所以要监听success
事件。会触发多次success事件,每次将数据绑定在event.target.result对象上。
下面封装方法查看指定数据库中指定表的所有数据。
function readAll(name,formName) {
let request = window.indexedDB.open(name)
let db=request.result
let objectStore = db.transaction(formName).objectStore(formName);
objectStore.openCursor().onsuccess = function (event) {
let 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('没有更多数据了!');
}
};
}
更新数据
更新数据库中已有的数据
IDBDatabase.transaction([formName]).objectStore(formName).objectStore.put(obj)
会查找obj.id(主键)值对应的一条数据,把该条数据中对应的值都更新一遍。
下面封装了更新指定数据库的指定表名的数据为obj。
function update(name,formName,obj) {
let request = window.indexedDB.open(name)
let db=request.result
let request = db.transaction([formName], 'readwrite')
.objectStore(formName)
.put(obj);
request.onsuccess = function (event) {
console.log('数据更新成功');
};
request.onerror = function (event) {
console.log('数据更新失败');
}
}
删除数据
IDBDatabase.transaction([formName]).objectStore(formName).objectStore.delete(primaryValue)
会查找主键值对应为primaryValue的一条数据,把该条数据从数据库中删除。
下面封装了删除指定数据库的指定表名的主键值为primaryValue的一条数据。
function remove(name,formName,primaryValue) {
let request = window.indexedDB.open(name)
let db=request.result
let res = db.transaction([formName], 'readwrite')
.objectStore(formName)
.delete(primaryValue);
res.onsuccess = function (event) {
console.log('数据删除成功');
};
}
使用索引
索引的意义在于,可以让你搜索任意字段,也就是说从任意字段拿到数据记录。如果不建立索引,默认只能搜索主键(即从主键取值)。
假定新建表格的时候,对name
字段建立了索引。
objectStore.createIndex('name', 'name', { unique: false });
之后可以从name
找到对应的数据记录了。
例如下面代码打开数据库,读取person表中的name属性对应为李四的一条数据。在success事件中通过e.target.result查看对象。
let request = window.indexedDB.open(name)
let db=request.result
let transaction = db.transaction(['person'], 'readonly');
let store = transaction.objectStore('person');
let index = store.index('name');
let rest = index.get('李四');
res.onsuccess = function (e) {
var result = e.target.result;
if (result) {
// ...
} else {
// ...
}
}
更多推荐
所有评论(0)