indexDB数据库初学之一

  • indexDB就是浏览器内置的前端数据库,跟localStorage等一样可进行存储,不过indexDB可以存储250~300MB,当然又优点也会有缺点,选择适合项目的就可以,下面简单的介绍下如何使用
  • 连接数据库
const data = reactive({
                db: null,
                storeName: 'test', //当前的数据库名
                version: 1, //版本号
                obj: {
                    name: 4,
                    id: 4,
                    age: 66,
                    list: [1, 2, 3]
                }
            })
function init(data) {
        const request = (window.indexedDB || window.webkitIndexedDB).open(data.storeName, data
            .version)
        request.onsuccess = e => {
            console.log('数据库打开成功', e.target.result);
            data.db = e.target.result
        }
        request.onerror = e => {
            console.log('数据库启动报错', e);
            throw Error('数据库报错啦:' + e.target.result)
        }
        //数据库创建或者升级的时候都会触发
        request.onupgradeneeded = e => {
            data.db = e.target.result
            let objectStore = null
            if (!data.db.objectStoreNames.contains(data.storeName)) {
                //在数据库中创建表group,设置主键为id,属性中必须要有id的字段
                objectStore = data.db.createObjectStore(data.storeName, {
                    keyPath: 'id'
                })
                //创建索引indexName指向表中的name字段且设为唯一值,不能重复,属性中可以没有name属性,但是id必须要有
                objectStore.createIndex('indexName', 'name', {
                    unique: true
                }) // 创建索引 可以让你搜索任意字段

            }
        }
    }

  • 上面的代码中使用了id作为主键,在添加的属性中必须要有id这个字段,storeName是数据库的名字,可以有多个数据库

  • 添加数据

 //添加数据
    const addData = (db, storeName, obj) => {
        //readwrite 读写操作的权限
        const request = db.transaction([storeName], 'readwrite').objectStore(storeName).add(obj)
        request.onsuccess = e => {
            console.log('写入成功', e.target.result);
            //这里可以做一些操作,添加第一次之后数据还是相同的就要进行阻止或者清空,否则报错
            //readyState为done是添加完毕
        }
        request.onerror = e => {
            console.log('写入失败:', e);
            throw Error('写入失败:' + e.target.result)
        }
    }

这里是使用vue进行练习的,如果你的添加数据使用的是响应式的,那么就需要转为原始的数据才可以添加成功,reactive转为toRaw

  • 获取数据
// 获取某一条数据
    const getData = (db, storeName, key) => {
        // transaction 第二个参数不写,默认是只读,key是当前属性的id值
        const request = db.transaction([storeName]).objectStore(storeName).get(key)
        request.onsuccess = e => {
            console.log('读取成功', e.target.result);

        }
        request.onerror = e => {
            console.log('读取失败:', e);
            throw Error('读取失败:' + e.target.result)
        }
    }
  • 获取当前数据库下当前表下的全部数据
 const getAllData = (db, storeName) => {
        // transaction 第二个参数不写,默认是只读
        const request = db.transaction([storeName]).objectStore(storeName).getAll()
        request.onsuccess = e => {
            console.log('读取全部成功', e.target.result);

        }
        request.onerror = e => {
            console.log('读取全部失败:', e);
            throw Error('读取全部失败:' + e.target.result)
        }
    }
  • 通过索引值进行查询数据
 // 通过索引name获取数据
    const getNameData = (db, storeName, name) => {
        // transaction 第二个参数不写,默认是只读
        const request = db.transaction([storeName]).objectStore(storeName).index('indexName').get(name)
        request.onsuccess = e => {
            console.log('读取索引成功', e.target.result);

        }
        request.onerror = e => {
            console.log('读取索引失败:', e);
            throw Error('读取索引失败:' + e.target.result)
        }
    }
  • 更新某一条数据
 // 更新某一条数据
    const upData = (db, storeName, data) => {
        // data 是当前的某一条数据更新的对象
        const request = db.transaction([storeName], 'readwrite').objectStore(storeName).put(data)
        request.onsuccess = e => { //readyState为done是更新完毕,或者result会返回当前的id值可进行判断
            console.log(e.target.result, e.target);
            console.log('更新成功', e.target.result);

        }
        request.onerror = e => {
            console.log('更新失败:', e);
            throw Error('更新失败:' + e.target.result)
        }
    }
  • 删除某一条数据
  // 删除某一条数据
    const deleteData = (db, storeName, key) => {
        const request = db.transaction([storeName], 'readwrite').objectStore(storeName).delete(key); //key---id值
        request.onsuccess = e => { //readyState为done是更新完毕
            console.log(e.target.result, e.target);
            console.log('删除成功', e.target.result);

        }
        request.onerror = e => {
            console.log('删除失败:', e);
            throw Error('删除失败:' + e.target.result)
        }
    }
  • 遍历当前表下的所有数据,第二个方法可做分页的操作
 // 使用指针遍历所有值使用id
    const fORData = (db, storeName) => {
        const request = db.transaction([storeName], 'readwrite').objectStore(storeName)
        request.openCursor().onsuccess = e => { //readyState为done是更新完毕
            var cursor = event.target.result;
            if (cursor) {
                console.log("当前的id值: " + cursor.key + " 和age值 " + cursor.value.age);
                cursor.continue();
            } else {
                console.log("结束遍历");
            }

        }
        request.onerror = e => {
            console.log('遍历所有值失败:', e);
            throw Error('遍历所有值失败:' + e.target.result)
        }
    }
    // 使用指针遍历所有值,使用name索引
    const fORData1 = (db, storeName) => {
        const objectStore = db.transaction([storeName]).objectStore(storeName)
        var index = objectStore.index("indexName");
        const range = IDBKeyRange.bound(1, 10); //遍历id从1到10的数据
        index.openCursor(range).onsuccess = function (event) {
            var cursor = event.target.result;
            if (cursor) {
                console.log("当前的name值: " + cursor.key + " 和age值 " + cursor.value.id);
                cursor.continue();
            } else {
                console.log("结束遍历");
            }
        };

        index.openCursor(range).onerror = e => {
            console.log('遍历所有值失败:', e);
            throw Error('遍历所有值失败:' + e.target.result)
        }
    }
  • 最后整体的代码如下
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>

<body>
    <div id="app">
        <button @click="startDB">启动数据库</button>
        <button @click="addBase">添加数据</button>
        <button @click="getBase">读取数据</button>
        <button @click="getNameBase">读取索引数据</button>
        <button @click="getAllBase">读取全部数据</button>
        <button @click="upBase">更新数据</button>
        <button @click="deleteBase">删除数据</button>
        <button @click="forBase">指针遍历</button>
    </div>
</body>

</html>
<script>
    const {
        createApp,
        reactive,
        toRefs,
        toRaw
    } = Vue

    createApp({
        setup() {
            const data = reactive({
                db: null,
                storeName: 'test', //当前的数据库名
                version: 1, //版本号

                obj: {
                    name: 44,
                    id: 44,
                    age: 66,
                    list: [1, 2, 3]
                }

            })
            // 启动数据库
            const startDB = () => {
                init(data)
            }
            //添加数据

            const addBase = () => {
                //使用reactive会将数据变为响应式,添加会报错,将响应式数据转为原始对象(不是响应式的就可以存储)
                addData(data.db, data.storeName, toRaw(data.obj))
            }

            // 获取数据

            const getBase = () => {
                getData(data.db, data.storeName, 7) //根据id进行读取
            }
            // 更新某一项
            const upBase = () => {
                upData(data.db, data.storeName, {
                    id: 6,
                    age: 222,
                    list: 333
                }) //根据id进行读取
            }
            // 删除某一项
            const deleteBase = () => {
                deleteData(data.db, data.storeName, 5) //根据id进行读取
            }
            // 读取全部的数据
            const getAllBase = () => {
                getAllData(data.db, data.storeName)
            }
            // 读取索引的数据
            const getNameBase = () => {
                getNameData(data.db, data.storeName, 6)
            }
            const forBase = () => {
                fORData(data.db, data.storeName) //遍历有id值
                fORData1(data.db, data.storeName) //遍历通过name索引


            }
            return {
                startDB,
                addBase,
                getBase,
                upBase,
                deleteBase,
                getAllBase,
                getNameBase,
                forBase,
                ...toRefs(data)
            }
        }
    }).mount('#app')

    function init(data) {
        const request = (window.indexedDB || window.webkitIndexedDB).open(data.storeName, data
            .version)
        request.onsuccess = e => {
            console.log('数据库打开成功', e.target.result);
            data.db = e.target.result
        }
        request.onerror = e => {
            console.log('数据库启动报错', e);
            throw Error('数据库报错啦:' + e.target.result)
        }
        //数据库创建或者升级的时候都会触发
        request.onupgradeneeded = e => {
            data.db = e.target.result
            let objectStore = null
            if (!data.db.objectStoreNames.contains(data.storeName)) {
                //在数据库中创建表group,设置主键为id,属性中必须要有id的字段
                objectStore = data.db.createObjectStore(data.storeName, {
                    keyPath: 'id'
                })
                //创建索引indexName指向表中的name字段且设为唯一值,不能重复,属性中可以没有name属性,但是id必须要有
                objectStore.createIndex('indexName', 'name', {
                    unique: true
                }) // 创建索引 可以让你搜索任意字段

            }
        }
    }

    //添加数据
    const addData = (db, storeName, obj) => {
        //读写操作
        const request = db.transaction([storeName], 'readwrite').objectStore(storeName).add(obj)
        request.onsuccess = e => {
            console.log('写入成功', e.target.result);

        }
        request.onerror = e => {
            console.log('写入失败:', e);
            throw Error('写入失败:' + e.target.result)
        }
    }
    // 获取数据
    const getData = (db, storeName, key) => {
        // transaction 第二个参数不写,默认是只读
        const request = db.transaction([storeName]).objectStore(storeName).get(key)
        request.onsuccess = e => {
            console.log('读取成功', e.target.result);

        }
        request.onerror = e => {
            console.log('读取失败:', e);
            throw Error('读取失败:' + e.target.result)
        }
    }
    // 通过索引name获取数据
    const getNameData = (db, storeName, name) => {
        // transaction 第二个参数不写,默认是只读
        const request = db.transaction([storeName]).objectStore(storeName).index('indexName').get(name)
        request.onsuccess = e => {
            console.log('读取索引成功', e.target.result);

        }
        request.onerror = e => {
            console.log('读取索引失败:', e);
            throw Error('读取索引失败:' + e.target.result)
        }
    }
    // 获取数据
    const getAllData = (db, storeName) => {
        // transaction 第二个参数不写,默认是只读
        const request = db.transaction([storeName]).objectStore(storeName).getAll()
        request.onsuccess = e => {
            console.log('读取全部成功', e.target.result);

        }
        request.onerror = e => {
            console.log('读取全部失败:', e);
            throw Error('读取全部失败:' + e.target.result)
        }
    }
    // 更新某一条数据
    const upData = (db, storeName, data) => {
        const request = db.transaction([storeName], 'readwrite').objectStore(storeName).put(data)
        request.onsuccess = e => { //readyState为done是更新完毕,或者result会返回当前的id值可进行判断
            console.log(e.target.result, e.target);
            console.log('更新成功', e.target.result);

        }
        request.onerror = e => {
            console.log('更新失败:', e);
            throw Error('更新失败:' + e.target.result)
        }
    }
    // 删除某一条数据
    const deleteData = (db, storeName, key) => {
        const request = db.transaction([storeName], 'readwrite').objectStore(storeName).delete(key); //key---id值
        request.onsuccess = e => { //readyState为done是更新完毕
            console.log(e.target.result, e.target);
            console.log('删除成功', e.target.result);

        }
        request.onerror = e => {
            console.log('删除失败:', e);
            throw Error('删除失败:' + e.target.result)
        }
    }
    // 使用指针遍历所有值使用id
    const fORData = (db, storeName) => {
        const request = db.transaction([storeName], 'readwrite').objectStore(storeName)
        request.openCursor().onsuccess = e => { //readyState为done是更新完毕
            var cursor = event.target.result;
            if (cursor) {
                console.log("当前的id值: " + cursor.key + " 和age值 " + cursor.value.age);
                cursor.continue();
            } else {
                console.log("结束遍历");
            }

        }
        request.onerror = e => {
            console.log('遍历所有值失败:', e);
            throw Error('遍历所有值失败:' + e.target.result)
        }
    }
    // 使用指针遍历所有值,使用name索引
    const fORData1 = (db, storeName) => {
        const objectStore = db.transaction([storeName]).objectStore(storeName)
        var index = objectStore.index("indexName");
        const range = IDBKeyRange.bound(1, 10); //遍历id从1到10的数据
        index.openCursor(range).onsuccess = function (event) {
            var cursor = event.target.result;
            if (cursor) {
                console.log("当前的name值: " + cursor.key + " 和age值 " + cursor.value.id);
                cursor.continue();
            } else {
                console.log("结束遍历");
            }
        };

        index.openCursor(range).onerror = e => {
            console.log('遍历所有值失败:', e);
            throw Error('遍历所有值失败:' + e.target.result)
        }
    }
</script>
  • 代码中的onsuccess和onerror函数可以封装一个公共的或者你有更好的方式
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345