前端存储 之 indexDB

1、indexedDB是什么?
  • indexedDB是一个非关系型数据库

  • 它不需要我们去写一些特定的SQL语句来对数据库进行操作

  • 它是NoSQL的,数据形式使用的json

2、indexedDB出现的意义?
  • 前端存储,已经有了LocalStorage 和 Cookies ,但是它们都是比较简单的技术。

  • 而indexedDB提供了 类似数据库风格的数据储存 和 使用方式

  • Cookies只能是字符串,储存空间有限,每次HTTP接受和发送都会传递Cookies数据,它会占用额外的流量

  • LocalStorage是用key-value 键值模式储存数据,想让localstorage存储对象,你需要借助JSON.stringify() 能将对象变成字符串形式,再用JSON.parse() 将字符串还原成对象,当存储的数据庞大时,这就不是最佳的方案了,localstorage就是专门为小数量数据设计的,它的api设计为同步的

  • indexedDB很适合存储大量数据,它的API是异步调用的,indexedDB使用索引存储数据,各种数据库操作放在事务中执行,indexedDB支持简单的数据类型,它比localstorage强大,API也相对复杂,对于简单的数据,还是使用localstorage。

  • indexedDB能提供更为复杂的查询数据的方式

3、indexedDB的特性
  • 对象仓库(objectStore)

    • indexedDB没有表的概念,而是使用objectStore。

    • 一个数据库中可以包含多个objectStore

    • objectStore是一个灵活的数据结构,可以存放多种类型数据,也就是说一个objectStore相当于一张表,里面储存的每条数据和一个键相关。

    • 我们可以使用每条记录中的某个字段作为键值(keyPath),也可以使用自动生成的递增数字作为键值(keyGenerator),也可以不指定。

    • 选择键的类型不同,objectStore可以存储的数据结构也有差异

  • 事务性

    • 在indexedDB中,每一个对数据库操作是在一个事务的上下文中执行的。

    • 事务范围一次影响一个或多个objectstores。

    • 你通过传入一个objectstores名字的数组到创建事务 范围的函数来定义

      • 比如: db.transaction( storeName, ' readwrite' ),创建事务的第二个参数是事务模式,当请求一个事务时,必须决定是按照只读还是读写模式模式请求访问

  • 基于请求

    • 对indexedDB数据库的每次操作,描述为通过一个请求打开数据库,访问一个object store,再继续。

    • indexedDB API天生是基于请求的,这也是API异步本性指示,对于你在数据库执行的每次操作,你必须首先为这个操作创建一个请求,当请求完成,你可以响应由请求结果产生的事件和错误

  • 异步

    • 在indexedDB 大部分操作并不是我们常用的调用方法,返回结果的模式,而是请求 ----> 响应的模式

    • 所谓异步API是指并不是这条指令执行完毕,我们就可以使用 request.result 来获取 indexedDB 对象了。

    • 类似于 我们使用ajax一样,语句执行完并不代表已经获取到了对象,所以我们一般在其回调函数中处理。

4、玩 indexedDB 的基本步骤

  1. 打开数据库并且开始一个事务

  2. 创建一个 object store

  3. 构建一个请求执行一些数据库操作,比如新增或者提取数据等

  4. 通过监听正确类型的DOM事件可以等待操作完成

  5. 在操作结果上进行一些操作(可以在 request 对象中找到)

代码案例:

1、打开数据库,需要当前浏览器支持indexedDB

var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;

if( !indexedDB ){
alert('当前不支持 indexedDB 数据库');
throw Error('当前不支持 indexed 数据库');
}

2、创建数据库

function createDB(dbName, version) {
// 参数为:数据库名和版本号
// 数据库存在则打开,否则创建
let request = indexedDB.open(dbName, version);
/**
* request 并不会返回一个DB对象的句柄,我们得到的是一个IDBOpenDBRequest对象
* 而我们期望得到的DB对象在其result属性中
* 除了 result,IDBOpenDBRequest 接口定义了几个重要属性
* onerror:请求失败的回调函数句柄
* onsuccess:请求成功的回调函数句柄
* onupgradeneeded:请求数据库版本变化句柄
* 第一次打开数据库,会先触发 onupgradeneeded 事件,然后触发success事件。
*/
console.log(request);

// 请求数据库失败的回调函数
request.onerror = function(err) {
console.log(JSON.stringify(err));
console.log('打开数据库失败,错误信息为:' + err.target.message);
}

// 请求数据库成功的回调函数
request.onsuccess = function(success) {
console.log(JSON.stringify(success));
console.log('打开数据库成功:' + success.target.result);

/**
* 获取数据库实例对象,
* db.createObjectStore('table6',{keyPath:'stuId',autoIncrement:true});
* var len = db.objectStoreNames.length; --> 对象储存空间名的个数
* var name = db.objectStoreNames[1]; --> 对象存储空间名
* transaction = db.transaction(['table'],'readwrite'); --> 事务操作的对象存储空间名,事务模式:'readwrite'可读写模式
*
* // 向info储存空间加入一个info对象,获得request对象用于处理用户对数据库的操作请求
* // 同样拥有 onerror 、onupgradeneeded 、onsuccess 事件
* objectStore = transaction.objectStore('table');
*/
let db = success.target.result;
}

// 数据库版本更新
request.inuparadeneeded = function(event) {
console.log(JSON.stringify(event));
console.log('数据库版本有变化...');

let db = event.target.result;

// 判断对象储存空间名称是否存在
if (!db.objectStoreNames.contains('table')) {


//创建信息对象存储空间;指定keyPath选项为Id(即主键为Id)
let objectStore = db.createObjectStore('table', {
keyPath: 'stuId',
autoIncrement: true
});
/*
*db.createObjectStore("table1", {keyPath: "userId",autoIncrement: true});
*db.createObjectStore("table2", {keyPath: "userId",autoIncrement: true});
*db.createObjectStore("table3", {keyPath: "userId",autoIncrement: true});
*db.createObjectStore("table4", {keyPath: "userId",autoIncrement: true});
*当然了。你可以一次性的在这里建立多个对象空间 或者每次改变 version和对象空间的名字。之前创建的会存在。
* 为什么在onupgradeneeded中创建呢?
* 原因:当dbName和 version 这两个参数中的任何一个发生变化。都会执行重新创建一遍对象空间,
* 注意:当dbName,保持不变,version 只能逐渐增加,假如你这次 version = 3.那么下次 version = 2.就会报错 打开数据库失败:
* version!=0;
* */


// 创建索引
// 索引名,创建索引的列,索引选项(索引属性值是否唯一:true or false)
// 注意: 创建索引 要在创建对象空间的时候
// unique:true 实际效果:这个索引的内容是唯一的,不能重复,无法创建两个(索引属性值)相同的内容
objectStore.createIndex('studentIndex', 'stuId', {
unique: true
});
}
}

}

3、删除数据库 or 关闭数据库

// 关闭与删除数据库
function deleteDB(dbName) {

try {
// 删除数据库使用 indexedDB对象的deleteDatabase方法
let request = indexedDB.deleteDatabase(dbName);

request.onerror = function() {
console.log('删除[' + dbName + ']数据库失败!!!!');
}

request.onsuccess = function() {
console.log('删除[' + dbName + ']数据库成功!!!!');
}

} catch (e) {
console.log('删除[' + dbName + ']数据库出现错误,' + e.getMessage);
}
}

// 关闭数据库
function colseDB(dbName){
dbName.close();
}

4、新增数据

// 新增数据
// 数据库名称,对象仓库(表名),传入的参数
function insert(dbName, objectStoreName, argument) {
// 打开数据库
let request = indexedDB.open(dbName);
// 请求数据库成功的回调函数
request.onsuccess = function(success) {
// 获取数据库实例对象
let db = success.target.result;
// 对某个表 进行事务操作的事务权限控制
let transaction = db.transaction(objectStoreName, 'readwrite');
// 对表进行操作
let objectStore = transaction.objectStore(objectStoreName);

// 使用add方法,此方法是异步的
// 有success,error事件
//objectStore.add(argument);
// 使用定义add方法
let add = objectStore.add(argument); let msg = JSON.stringify(argument); // 添加成功的回调函数
add.onsuccess = function(e) {
console.log(e);
console.log('向表[' + objectStoreName + ']新增一条数据为[' + msg + ']成功!!');
}
add.error = function(e) {
console.log('向表[' + objectStoreName + ']新增一条数据为[' + msg + ']失败!!');
}
}

}

var stu1 = {
name: '欧可乐',
age: 19,
sex: '男'
};

insert('studentDB','student',stu1);

5、查询数据

// 查询数据
// 数据库名,对象仓库(表名),查询参数(键名对应的值)
function getData(dbName, objectStoreName, selectArgument){
// 打开数据库
let request = indexedDB.open(dbName);
// 请求打开数据库的回调函数
request.onsuccess = function(success){
let db = success.target.result;
let transaction = db.transaction([objectStoreName],'readwrite');
let objectStore = transaction.objectStore(objectStoreName);
let getResult = objectStore.get(selectArgument);

getResult.onsuccess = function(e){
console.log( e.target.result);
}

}

}

getData('studentDB','student',1);

6、更新数据

// 更新数据
// 数据库名,表名,要更新数据的标志(id),新的数据
function update(dbName, objectStoreName, id, newsData) {
// 打开数据库
let request = indexedDB.open(dbName);
// 请求打开数据库的回调函数
request.onsuccess = function(success) {
// 获取到数据库的表
let db = success.target.result;
// 对表操作进行事务权限控制
let transaction = db.transaction(objectStoreName, 'readwrite');
// 对表进行操作
let objectStore = transaction.objectStore(objectStoreName);
// 根据键值 获取某个实例中的某条数据
let getResult = objectStore.get(id);
// 实例成功的回调函数
getResult.onsuccess = function(e) {
// 源数据
let msg = e.target.result;
let old = JSON.stringify(msg);
// 重新赋值
msg.name = newsData.name;
msg.age = newsData.age;
msg.sex = newsData.sex;
objectStore.put(msg);
console.log('更新主键为 stuId:' + msg.stuId + '的数据,原数据:[' + old + '],新数据为:[' + JSON.stringify(e.target.result) +
'],更新成功!!!');
}
// 实例失败的回调函数
getResult.onerror = function(e) {
console.log('数据更新失败!!');
}
}
}

let stu2 = {
name: '小可乐',
age: 18,
sex: '男'
}
update('studentDB', 'student', 1, stu2);

7、删除数据

// 删除数据
// 数据库名,表名,主键
function deleteData(dbName, tableName, id){
// 打开数据库
let request = indexedDB.open(dbName);
// 请求打开数据库成功的回调函数
request.onsuccess = function(success){
// 获取实例
let db = success.target.result;
// 事务权限控制
let transaction = db.transaction(tableName, 'readwrite');
// 进行操作
let objectStore = transaction.objectStore(tableName);
// 进行删除
let deleteMsg = objectStore.delete(id);
deleteMsg.onsuccess = function(e){
console.log('成功删除主键stuId为:' + id+',的数据,状态为:'+e.isTrusted);
}
}
}

deleteData('studentDB','student',1);

8、清除表数据

// 清空表数据
// 数据库名称,表名
function clearData(dbName, tableName) {
// 请求打开数据库
let request = indexedDB.open(dbName);
// 请求成功的回调函数
request.onsuccess = function(e) {
// 获取实例
let db = e.target.result;
// 表名事务权限控制
let transaction = db.transaction(tableName, 'readwrite');
// 进行操作
let objectStore = transaction.objectStore(tableName);
// 清除数据
let clearResult = objectStore.clear();
// 清除成功的回调函数
clearResult.onsuccess = function(e) {
console.log('表名[' + tableName + ']数据清除成功,状态为:' + e.isTrusted );
}
}
}
clearData('studentDB', 'student');

9、使用索引查询

// 利用索引查询
// 数据库,表名,索引名, 查询的值
function searchIndex(dbName, tableName, indexName, indexValue) {
// 请求打开数据
let request = indexedDB.open(dbName);
// 请求打开数据库成功的回调函数
request.onsuccess = function(e) {
// 获取到实例
let db = e.target.result;
// 赋予事务权限
let transaction = db.transaction(tableName, 'readwrite');
// 基于权限进行操作
let objectStore = transaction.objectStore(tableName);
// 索引
let index = objectStore.index(indexName);
// 获取结果
let result = index.get(indexValue);
// 结果获取成功的回调函数
result.onsuccess = function(e) {
console.log('索引名:' + indexName + ',索引值:' + indexValue + ',查询的结果:[' + JSON.stringify( e.target.result ) + ']');
}
}
}
searchIndex('studentDB','student','studentIndex',2);

10、使用游标读取全部的数据

// 使用 游标
// 数据库名称,表名
function readAll(dbName, tableName) {
// 请求打开数据库
let request = indexedDB.open(dbName);
// 请求成功的回调函数
request.onsuccess = function(e) {
// db = e.target.result // 获取实例
// transaction = db.transaction(tableName,'readwrite'); // 权限控制
// objectStore = transaction.objectStore(tableName); // 进行操作对象
let objectStore = e.target.result.transaction(tableName, 'readwrite').objectStore(tableName);
// 打开游标
let cursor = objectStore.openCursor();

// 储存值
let arr = [];

// 成功打开游标的回调函数
cursor.onsuccess = function(e) {
let result = e.target.result;

if (result) {
// 将数据一条一条保存到arr中
arr.push(result.value);
result.continue();
} else {
if (!arr) {
console.log('没有数据....');
} else {
console.log('[' + tableName + ']表中的数据为:' + JSON.stringify(arr));
}
}
}
}
}
readAll('studentDB', 'student');

indexedDB 前端数据库(使用的简单案例)的更多相关文章

  1. [Design Pattern] Front Controller Pattern 简单案例

    Front Controller Pattern, 即前端控制器模式,用于集中化用户请求,使得所有请求都经过同一个前端控制器处理,处理内容有身份验证.权限验证.记录和追踪请求等,处理后再交由分发器把请 ...

  2. Struts2学习笔记NO.1------结合Hibernate完成查询商品类别简单案例(工具IDEA)

    Struts2学习笔记一结合Hibernate完成查询商品类别简单案例(工具IDEA) 1.jar包准备 Hibernate+Struts2 jar包 struts的jar比较多,可以从Struts官 ...

  3. RSA加密算法的简单案例

    RSA加密算法是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击. 那关于RSA加密算法有哪些应用呢?以下举一个数据库身份验证的案例. 在使用数据集进行身份认证时,密码存在数据 ...

  4. Ajax与ashx异步请求的简单案例

    Ajax与ashx异步请求的简单案例: 前台页面(aspx): <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//E ...

  5. WPF+MVVM学习总结 DataGrid简单案例

    一.WPF概要 WPF(Windows Presentation Foundation)是微软推出的基于Windows 的用户界面框架,属于.NET Framework 3.0的一部分.它提供了统一的 ...

  6. 15.5 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表

    点击返回:自学Zabbix之路 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表  1. Actions表 actions表记录了当触发器触发时,需要采用的动作. 2.Aler ...

  7. springmvc 项目完整示例01 需求与数据库表设计 简单的springmvc应用实例 web项目

    一个简单的用户登录系统 用户有账号密码,登录ip,登录时间 打开登录页面,输入用户名密码 登录日志,可以记录登陆的时间,登陆的ip 成功登陆了的话,就更新用户的最后登入时间和ip,同时记录一条登录记录 ...

  8. 自学Zabbix之路15.2 Zabbix数据库表结构简单解析-Items表

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix之路15.2 Zabbix数据库表结构简单解析-Items表 Items表记录了i ...

  9. 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表  1. Actions表 ...

随机推荐

  1. poj 2362:square

    题目大意:给你T组数据,每组数据有n个棍子,问你能不能用这些棍子拼成一个正方形(所有都要用上,而且不能截断棍子). Sample Input 34 1 1 1 15 10 20 30 40 508 1 ...

  2. Oracle 查询id相同多个数据取一条

    涉及场景 需要查出同一ID下 COLUMN_A字段为数值型的 多条数据 只去COLUMN_A为最小值的那条 SELECT * FROM (SELECT A.ID, A.COLUMN_A, ROW_NU ...

  3. 杜教BM递推板子

    Berlekamp-Massey 算法用于求解常系数线性递推式 #include<bits/stdc++.h> typedef std::vector<int> VI; typ ...

  4. 关于日志slf4j+logback&logback.xml配置

    1.maven依赖 <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api --> <!-- <dependen ...

  5. 牛客 197C 期望操作数

    大意: 给定$x,q$, 每步操作$x$等概率变为$[x,q]$中任意一个数, 求变为$q$的期望操作数. 很容易可以得到$f(x,q)=\frac{\sum\limits_{i=x+1}^qf(i, ...

  6. 给postmessage加上callback方法

    postmessage双向通信中,是不能使用回调函数的. window.postmessage({msg:'hello',callback:function(e){ do something with ...

  7. layer,备受青睐的web弹层组件

    //http://layer.layui.com/ 特别说明:事件需自己绑定,以下只展现调用代码. //初体验 layer.alert('内容') //第三方扩展皮肤 layer.alert('内容' ...

  8. ant-design的Table组件自定义空状态

    Table,是antd中一个我们经常使用的组件,在官方文档中给出了非常详细的实例以及API, 但在我们在使用过程中可能需要根据项目的要求来定制空状态时的展示. 什么是空状态呢? 在antd的官方文档中 ...

  9. NET如何使用ELinq-实现增删改查

    1 通过对ELinq主页的参考和学习,以及在项目中(wpf项目中用到的)中应用,ORM框架中的ELinq确实非常的强大,特此以建立wpf项目为例子来总结下如何在项目中应用ELinq,要想使用这个框架首 ...

  10. PHP 求两个日期之间相差的天数、月数

    <?php /** * 求两个日期之间相差的天数 * (针对1970年1月1日之后,求之前可以采用泰勒公式) * @param string $day1 * @param string $day ...