indexedDB 前端数据库(使用的简单案例)
前端存储 之 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 的基本步骤
- 打开数据库并且开始一个事务 
- 创建一个 object store 
- 构建一个请求执行一些数据库操作,比如新增或者提取数据等 
- 通过监听正确类型的DOM事件可以等待操作完成 
- 在操作结果上进行一些操作(可以在 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 前端数据库(使用的简单案例)的更多相关文章
- [Design Pattern] Front Controller Pattern 简单案例
		Front Controller Pattern, 即前端控制器模式,用于集中化用户请求,使得所有请求都经过同一个前端控制器处理,处理内容有身份验证.权限验证.记录和追踪请求等,处理后再交由分发器把请 ... 
- Struts2学习笔记NO.1------结合Hibernate完成查询商品类别简单案例(工具IDEA)
		Struts2学习笔记一结合Hibernate完成查询商品类别简单案例(工具IDEA) 1.jar包准备 Hibernate+Struts2 jar包 struts的jar比较多,可以从Struts官 ... 
- RSA加密算法的简单案例
		RSA加密算法是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击. 那关于RSA加密算法有哪些应用呢?以下举一个数据库身份验证的案例. 在使用数据集进行身份认证时,密码存在数据 ... 
- Ajax与ashx异步请求的简单案例
		Ajax与ashx异步请求的简单案例: 前台页面(aspx): <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//E ... 
- WPF+MVVM学习总结 DataGrid简单案例
		一.WPF概要 WPF(Windows Presentation Foundation)是微软推出的基于Windows 的用户界面框架,属于.NET Framework 3.0的一部分.它提供了统一的 ... 
- 15.5 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表
		点击返回:自学Zabbix之路 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表 1. Actions表 actions表记录了当触发器触发时,需要采用的动作. 2.Aler ... 
- springmvc 项目完整示例01 需求与数据库表设计 简单的springmvc应用实例 web项目
		一个简单的用户登录系统 用户有账号密码,登录ip,登录时间 打开登录页面,输入用户名密码 登录日志,可以记录登陆的时间,登陆的ip 成功登陆了的话,就更新用户的最后登入时间和ip,同时记录一条登录记录 ... 
- 自学Zabbix之路15.2 Zabbix数据库表结构简单解析-Items表
		点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix之路15.2 Zabbix数据库表结构简单解析-Items表 Items表记录了i ... 
- 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表
		点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表 1. Actions表 ... 
随机推荐
- Qt全局坐标和相对坐标
			QMouseEvent中两类坐标系统,一类是窗口坐标,一类是显示器坐标. QPoint QMouseEvent::pos() 返回相对这个widget(重载了QMouseEvent的widget)的位 ... 
- 第一次git到GitHub过程
			首先在GitHub上创建一个仓库 
- golang语言sql Rows转化保存成map
			func DoQuery(db *sql.DB, sqlInfo string, args ...interface{}) ([]map[string]interface{}, error) { ro ... 
- 《你必须知道的495个C语言问题》读书笔记之第8-10章:字符串、布尔类型和预处理器
			一.字符和字符串 1. Q:为什么strcat(string, '!')不行? A:strcat()用于拼接字符串,所以应该写成strcat(string, "!")." ... 
- [转帖]IBM 开源 POWER 指令集架构
			IBM 开源 POWER 指令集架构 https://www.solidot.org/story?sid=61791 新闻越短 事情越严重 IBM 破釜沉舟 OpenPOWER 联盟国产化披荆斩棘? ... 
- .net操作数据库
			1. 自动生化曾的一些查询 可以自定义查询语句 2.自定义查询过程调用 USE [mydb] GO /****** Object: StoredProcedure [dbo].[procLogin] ... 
- LG P2285 [模板]负环(spfa判负环)
			题目描述 寻找一个从顶点1所能到达的负环,负环定义为:一个边权之和为负的环. 输入格式 第一行一个正整数T表示数据组数,对于每组数据: 第一行两个正整数N M,表示图有N个顶点,M条边 接下来M行,每 ... 
- 洛谷 P2746 [USACO5.3]校园网Network of Schools
			题目描述 一些学校连入一个电脑网络.那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作“接受学校”).注意即使 B 在 A 学校的分发列表中, A 也不一定在 B 学校的列表中. 你要写 ... 
- Centos安装elasticsearch,php连接使用
			一.下载安装JAVA 下载地址:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html ... 
- hyper-v虚拟机centos7网络配置
			原文地址:https://jingyan.baidu.com/article/91f5db1b0279bd1c7e05e377.html hyper-v安装了centos7之后并不能上网,这里简单介绍 ... 
