indexDB的理解与使用

indexDB的理解与使用

创建数据库

const request = indexedDB.open('myDatabase', 1);
request.addEventListener('success', e => {
    console.log('连接数据库成功');
});

request.addEventListener('error', e => {
    console.log('连接数据库失败');
});

使用indexedDB.open()创建一个indexedDB数据库.open()方法接受可以接受两个参数.第一个是数据库名,第二个是数据库的版本号.同时返回一个IDBOpenDBRequest对象用于操作数据库.其中对于open()的第一个参数数据库名,open()会先去查找本地是否已有这个数据库,如果有则直接将这个数据库返回,如果没有,则先创建这个数据库,再返回.对于第二个参数版本号,则是一个可选参数,如果不传,默认为1.但如果传入就必须是一个整数.

在通过对indexedDB.open()方法拿到一个数据库对象IDBOpenDBRequest我们可以通过监听这个对象的success事件和error事件来执行相应的操作.

创建对象仓库

在有了一个数据库之后,我们获取就想要去存储数据了,但是单只有数据库还不够,我们还需要有对象仓库(object store).对象仓库(object store)是indexedDB数据库的基础,其类似于MySQL中表的概念.

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

const request = indexedDB.open('myDatabase', 2);
request.addEventListener('upgradeneeded', e => {
    const db = e.target.result;
    const store = db.createObjectStore('Users', {
        keyPath: 'userId',
        autoIncrement: false
    });
    console.log('创建对象仓库成功');
});

在上述代码中我们监听upgradeneeded事件,并在这个事件触发时使用createObjectStore()方法创建了一个对象仓库.createObjectStore()方法接受两个参数,第一个是对象仓库的名字,在同一数据库中,仓库名不能重复.第二个是可选参数.用于指定数据的主键,以及是否自增主键.

创建事务

简单来说事务就是用来保证数据库操作要么全部成功,要么全部失败的一个限制.比如,在修改多条数据时,前面几条已经成功了.,在中间的某一条是失败了.那么在这时,如果是基于事务的数据库操作,那么这时数据库就应该重置前面数据的修改,放弃后面的数据修改.直接返回错误,一条数据也不修改.

const request = indexedDB.open('myDatabase', 3);
request.addEventListener('success', e => {
    const db = e.target.result;
    const tx = db.transaction('Users', 'readwrite');
});

上述代码中我们使用transaction()来创建一个事务.transaction()接受两个参数,第一个是你要操作的对象仓库名称,第二个是你创建的事务模式.传入 readonly时只能对对象仓库进行读操作,无法写操作.可以传入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
    });
    reqAdd.addEventListener('success', e => {
        console.log('保存成功')
    })
});

获取数据

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 reqGet = store.get(1);
    reqGet.addEventListener('success', e => {
        console.log(this.result.userName);
    })
});

删除数据

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 reqDelete = store.delete(1);
    reqDelete.addEventListener('success', e => {
        console.log('删除数据成功');
    })
});

使用游标

在上面当中我们使用get()方法传入一个主键来获取数据,但是这样只能够获取到一条数据.如果我们想要获取多条数据了怎么办.我们可以使用游标,来获取一个区间内的数据.

要使用游标,我们需要使用对象仓库上的openCursor()方法创建币打开.openCursor()方法接受两个参数.

openCursor(range?: IDBKeyRange | number | string | Date | IDBArrayKey, direction?: IDBCursorDirection): IDBRequest;

第一个是范围,范围可以是一个IDBKeyRange对象.用以下方式创建.

ar boundRange = IDBKeyRange.bound(1, 10, false, false);
var onlyRange = IDBKeyRange.only(1);
var lowerRange = IDBKeyRange.lowerBound(1, false);
var upperRange = IDBKeyRange.upperBound(10, false);

第二个参数是方向.主要有一下几种

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 = this.result;
        if (cursor) {
            console.log(cursor.value.userName);
            cursor.continue();
        } else {
            console.log('检索结束');
        }
    })
});

在上面的代码中如果检索到符合条件的数据时,我们可以:

使用cursor.value拿到数据.
使用cursor.updata()更新数据.
使用cursor.delete()删除数据.
使用cursor.continue()读取下一条数据.

索引

创建索引

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

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

createIndex()方法接收三个参数:

第一个参数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
    })
});

使用索引

这在创建了一条索引之后我们就可以来使用它了.我们使用对象仓库上的index方法,通过传入一个索引名.来拿到一个索引对象.

const index = store.index('ageIndex');`

 然后我们就可以使用这个索引了.比如说我们要拿到年龄在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('检索结束');
        }
    })
});

实践

我们最后把上文中的操作连贯起来实现存取:

const request = indexedDB.open('myDatabase',2);
request.addEventListener('success', e => {
    console.log('连接数据库成功');
});

request.addEventListener('error', e => {
    console.log('连接数据库失败');
});

request.addEventListener('upgradeneeded', e => {
    const db = e.target.result;
    const store = db.createObjectStore('Users', {
        keyPath: 'userId',
        autoIncrement: false
    });
    console.log('创建对象仓库成功');
});

request.addEventListener('success', e => {
    const db = e.target.result;
    const tx = db.transaction('Users', 'readwrite');
});

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
    });
    reqAdd.addEventListener('success', e => {
        console.log('保存成功')
    })
});
request.addEventListener('success', e => {
    const db = e.target.result;
    const tx = db.transaction('Users', 'readwrite');
    const store = tx.objectStore('Users');
    const reqGet = store.get(1);
    reqGet.addEventListener('success', e => {
        console.log(e.srcElement.result);
        //这边用原文中的this会发现undefined
    })
});

结果:

连接数据库成功
创建对象仓库成功
{userId: 1, userName: "李白", age: 24}

的确是可行的。

猜你喜欢

转载自blog.csdn.net/YPJMFC/article/details/80503708