indexedDB

作者: pomelo_西 | 来源:发表于2019-11-19 16:10 被阅读0次

    原文地址: https://juejin.im/post/5b09a641f265da0dcd0b674f

    定义:

    IndexedDB 是一种使用浏览器存储大量数据的方法.它创造的数据可以被查询,并且可以离线使用. IndexedDB对于那些需要存储大量数据,或者是需要离线使用的程序是非常有效的解决方法.

    indexedDB也遵从同源协议(same-origin policy). 所以你只能访问同域中存储的数据,而不能访问其他域的。

    其简单而言, indexedDB就是一个基于事务操作的key-value型数前端数据库.其API大多是异步的

    使用:

    1. 创建数据库
    2. 创建对象仓库
    3. 创建事务
    创建数据库:
    // open后两个参数,一个是数据库名称,一个是版本号,返回一个IDBOpenDBRequest对象用于操作数据库
    const request = indexedDB.open('myDatabase', 1);
    // open()会先去查找本地是否已有这个数据库,如果有则直接将这个数据库返回,如果没有,则先创建这个数据库,再返回.对于第二个参数版本号,则是一个可选参数,如果不传,默认为1.但如果传入就必须是一个整数.
    
    request.addEventListener('success', e => {
       console.log("连接数据库成功");
    });
    
    request.addEventListener('error', e => {
        console.log("连接数据库失败");
    });
    
    创建一个对象仓库

    要创建一个对象仓库必须在upgradeneeded事件中,而upgradeneeded事件只会在版本号更新的时候触发.这是因为indexedDB API中不允许数据库中的数据仓库在同一版本中发生变化

    const request = indexedDB.open('myDatabase', 2);
    
    request.addEventListener('upgradeneeded', e => {
        const db = e.target.result;
    
        //createObjectStore()里的参数:第一个是对象仓库的名称;第二个是可选参数.用于指定数据的主键,以及是否自增主键.
        const  store = db.createObjectStore('Users', {keyPath: 'userId', autoIncrement: false});
        console.log('创建对象仓库成功');
    });
    
    创建事务

    事务:一个数据库事务通常包含了一个序列的对数据库的读/写操作。

    事务目的:

    • 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
    • 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰

    数据库事务有以下四个特性:

    • 原子性
    • 一致性
    • 隔离性
    • 持久性
    const request = indexedDB.open('myDatabase', 3);
    
    request.addEventListener('success', e => {
        const db = e.target.result;
    
        // transaction()有两个参数,第一个是对象仓库的名称;第二个是创建的事务模式,readonly只读,readwrite读写
        const tx = db.transaction('Users','readwrite');
    });
    
    操作数据
    • add() : 增加数据。接收一个参数,为需要保存到对象仓库中的对象。
    • put() : 增加或修改数据。接收一个参数,为需要保存到对象仓库中的对象。
    • get() : 获取数据。接收一个参数,为需要获取数据的主键值。
    • delete() : 删除数据。接收一个参数,为需要获取数据的主键值。

    add 和 put 区别在于 put 保存数据时,如果该数据的主键在数据库中已经有相同主键的时候,则会修改数据库中对应主键的对象,而使用 add 保存数据,如果该主键已经存在,则保存失败。

    const request = indexedDB.open('myDatabase', 3);
    
    request.addEventListener('success', e => {
        const db = e.target.result;
    
        const tx = db.transaction('Users','readwrite');
    
        const store = tx.objectStore('Users');
    
        // 保存数据
        const reqAdd = store.add({'userId': 1, 'userName': '李白', 'age': 24});
        // 修改数据
        const reqAdd = store.put({'userId': 1, 'userName': '李白', 'age': 23});
        // 获取数据,通过主键值获取
        const reqAdd = store.get(1);
        // 删除数据,通过主键值删除
        const reqAdd = store.delete(1);
    
        reqAdd.addEventListener('success', e => {
          console.log('保存成功')
        })
    });
    
    使用游标获取一个区间内的数据

    要使用游标,我们需要使用对象仓库上的openCursor()方法创建币打开.openCursor()方法接受两个参数:第一个是范围,范围可以是一个IDBKeyRange对象;第二个参数是方向

    openCursor(range?: IDBKeyRange | number | string | Date | IDBArrayKey, direction?: IDBCursorDirection): IDBRequest;
    
    1. 创建IDBKeyRange对象
    // boundRange 表示主键值从1到10(包含1和10)的集合。
    // 如果第三个参数为true,则表示不包含最小键值1,如果第四参数为true,则表示不包含最大键值10,默认都为false
    var boundRange = IDBKeyRange.bound(1, 10, false, false);
    
    // onlyRange 表示由一个主键值的集合。only() 参数则为主键值,整数类型。
    var onlyRange = IDBKeyRange.only(1);
    
    // lowerRaneg 表示大于等于1的主键值的集合。
    // 第二个参数可选,为true则表示不包含最小主键1,false则包含,默认为false
    var lowerRange = IDBKeyRange.lowerBound(1, false);
    
    // upperRange 表示小于等于10的主键值的集合。
    // 第二个参数可选,为true则表示不包含最大主键10,false则包含,默认为false
    var upperRange = IDBKeyRange.upperBound(10, false);
    
    1. 方向
    • next : 游标中的数据按主键值升序排列,主键值相等的数据都被读取
    • nextunique : 游标中的数据按主键值升序排列,主键值相等只读取第一条数据
    • prev : 游标中的数据按主键值降序排列,主键值相等的数据都被读取
    • prevunique : 游标中的数据按主键值降序排列,主键值相等只读取第一条数据

    例子:

    const request = indexedDB.open('myDatabase', 4);
    
    request.addEventListener('success', e => {
        const db = e.target.result;
    
        const tx = db.transaction('Users','readwrite');
    
        const store = tx.objectStore('Users');
    
        const range = IDBKeyRange.bound(1,10);
    
        const req = store.openCursor(range, 'next');
    
        req.addEventListener('success', e => {
            const cursor = e.target.result
            if(cursor){
                console.log(cursor.value.userName);
                cursor.continue();
            }else{
                console.log('检索结束');
            }
        })
    });
    
    索引

    我们知道一个大概的条件.比如说年龄大于20岁的用户.这个时候我们就需要用到索引.以便有条件的查找.

    创建索引:

    我们使用对象仓库的createIndex()方法来创建一个索引.

    createIndex(name: string, keyPath: string | string[], optionalParameters?: IDBIndexParameters): IDBIndex;
    

    第一个参数name是索引名,不能重复.

    第二个参数keyPath是你要在存储对象上的那个属性上建立索引,可以是一个单个的key值,也可以是一个包含key值集合的数组.

    第三个参数optionalParameters是一个可选的对象参数{unique, multiEntry}

    unique: 用来指定索引值是否可以重复,为true代表不能相同,为false时代表可以相同
    multiEntry: 当第二个参数keyPath为一个数组时.如果multiEntry是true,则会以数组中的每个元素建立一条索引.如果是false,则以整个数组为keyPath值,添加一条索引.

    const request = indexedDB.open('myDatabase', 5);
    
    request.addEventListener('upgradeneeded', e => {
        const db = e.target.result;
        const  store = db.createObjectStore('Users', {keyPath: 'userId', autoIncrement: false});
        const idx = store.createIndex('ageIndex','age',{unique: false})
    });
    

    然后我们就可以使用这个索引了.比如说我们要拿到年龄在20岁以上的数据,升序排列.

    const request = indexedDB.open('myDatabase', 4);
    
    request.addEventListener('success', e => {
        const db = e.target.result;
    
        const tx = db.transaction('Users','readwrite');
    
        const store = tx.objectStore('Users');
    
        const index = store.index('ageIndex');
    
        const req = index.openCursor(IDBKeyRange.lowerBound(20), 'next');
    
        req.addEventListener('success', e => {
          const cursor = e.target.result;
            if(cursor){
                console.log(cursor.value.age);
                cursor.continue();
            }else{
                console.log('检索结束');
            }
        })
    });
    

    原文出处:https://juejin.im/post/5b09a641f265da0dcd0b674f

    贴上完整代码
    createIndexDBStorage() {
      // open()有两个参数,分别是:数据库名,版本号
      const request = indexedDB.open('myDatabase', 1)
    
      request.addEventListener('upgradeneeded', (e) => {
        const db = e.target.result
    
        // 创建仓库,createObjectStore()有两个参数,第一个是仓库名,第二个设置仓库的主键以及是否自增长
        const store = db.createObjectStore('Users', { keyPath: 'userId', autoIncrement: false })
    
        // 创建索引,createIndex()第一个参数是索引名,不能重复
        // 第二个参数是你要建立索引的属性,可以是单个的key值,也可以是一个包含key值集合的数组
        // 第三个参数:unique,multiEntry
        const idx = store.createIndex('ageIndex', 'age', { unique: false })
      })
    },
    operateData() {
      const request = indexedDB.open('myDatabase', 1)
    
      request.addEventListener('success', (e) => {
        console.log('连接数据库成功')
        const db = e.target.result
    
        // 创建事务,transaction()第一个参数是仓库名
        // 第二个参数是事务模式,readonly是只读,readwrite是读写
        const tx = db.transaction('Users', 'readwrite')
        const store = tx.objectStore('Users')
    
        // 添加数据
        const req = store.add({ 'userId': 1, 'name': '李白', 'age': 24 })
        // 修改数据
        // const req = store.put({ 'userId': 1, 'name': '李白', 'age': 25 })
        // 根据主键值获取数据
        // const req =  store.get(1)
        // 根据主键值删除数据
        // const req =  store.delete(1)
        req.addEventListener('success', (e) => {
          console.log('成功添加/修改/删除')
        })
      })
    
      request.addEventListener('error', (e) => {
        console.log('连接数据库失败')
      })
    },
    // 根据游标获取数据
    getDataByKeyRange() {
      const request = indexedDB.open('myDatabase', 1)
    
      request.addEventListener('success', (e) => {
        const db = e.target.result
        const tx = db.transaction('Users', 'readwrite')
        const store = tx.objectStore('Users')
    
        // openCursor()第一个参数是范围:IDBKeyRange对象,第二个参数是方向
        const req = store.openCursor(IDBKeyRange.bound(1, 30), 'next')
        req.addEventListener('success', (e) => {
          let cursor = e.target.result
          if (cursor) {
            console.log(cursor.value)
            cursor.continue()
          } else {
            console.log('检索完毕')
          }
        })
      })
    },
    // 根据索引获取数据
    getDataByIndex() {
      const request = indexedDB.open('myDatabase', 1)
    
      request.addEventListener('success', (e) => {
        const db = e.target.result
        const tx = db.transaction('Users', 'readwrite')
        const store = tx.objectStore('Users')
        const index = store.index('ageIndex')
    
        // openCursor()第一个参数是范围:IDBKeyRange对象,第二个参数是方向
        const req = index.openCursor(IDBKeyRange.bound(1, 30), 'next')
        req.addEventListener('success', (e) => {
          let cursor = e.target.result
          if (cursor) {
            console.log(cursor.value)
            cursor.continue()
          } else {
            console.log('检索完毕')
          }
        })
      })
    }
    

    相关文章

      网友评论

          本文标题:indexedDB

          本文链接:https://www.haomeiwen.com/subject/jzgwictx.html