• 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 的基本步骤

    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');
  • 相关阅读:
    [AGC030F] Permutation and Minimum
    [GYM102904B]Dispatch Money
    [ZOJ3989]Triangulation
    [HDU6094]Rikka with KMatch
    CF739E Gosha is hunting
    [国家集训队]Tree I
    [BZOJ3864]Hero meet devil
    编程是一门实践性的科学
    IE下的flash加载中文URL文件 问题
    多线程1号
  • 原文地址:https://www.cnblogs.com/oukele/p/10727790.html
Copyright © 2020-2023  润新知