在现代浏览器的本地存储方案中,indexedDB 是一项重要的能力组成, 它是可以在浏览器端使用的本地数据库,可以存储大量数据,提供接口来查询,还可以建立索引,这些都是其他存储方案 Cookie 或者 LocalStorage 无法提供的能力。单从数据库类型来看,IndexedDB 是一个非关系型数据库(不支持通过 SQL 语句操作)。
IndexedDB 的主要概念
IndexedDB 是一个比较复杂的 API 组合,学习它的过程就相当于学习它的各个对象 API 接口,包括以下这些( IDB 指当前操作的数据库实例 ):
在这些 API 中包含一些主要概念:
通过简单的对比图来理解 IndexedDB 的概念:
快速起步 IndexedDB
在介绍了 IndexedDB 的主要概念之后,可以通过一个简单实用的 CURD 例子来学习在日常开发中我们是怎么使用 IndexedDB 的,各个 API 细节日后可以慢慢深入学习。
if(!('indexedDB' in window)){ console.log('当前浏览器支持 IndexedDB'); return; } else { console.log('您的浏览器不支持 IndexedDB') // todo 建议升级或者更换其他浏览器 }
// 数据库实例 let db; // 数据库打开操作,第一个参数是数据库名称, 第二个参数是数据库版本 let DBRequestLink = window.indexedDB.open('dataBaseName', 1) DBRequestLink.onsuccess = function(event) { // 获取数据库实例 db = DBRequestLink.result; // 其他操作 }; // 这个监听回调触发于数据库首次新建、open数据库时传递新版本(只能比之前传递的版本高) DBRequestLink.onupgradeneeded = function(event) {};
DBOpenRequest.onupgradeneeded = function(event) { let db = event.target.result; // 创建一个数据库存储对象,并指定主键 let objectStore = db.createObjectStore('person', { keyPath: 'id', autoIncrement: true }); /* 定义存储对象的数据项 * 第一个参数是创建的索引名称,可以为空 * 第二个参数是索引使用的关键名称,可以为空 * 第三个参数是可选配置参数,可以不传,常用参数之一就是 unique ,表示该字段是否唯一,不能重复 */ objectStore.createIndex('id', 'id', { unique: true }); objectStore.createIndex('name', 'name'); objectStore.createIndex('age', 'age'); objectStore.createIndex('sex', 'sex'); };
// 这里的 db 就是第二步中的 db 对象, // transaction api 的第一个参数是数据库名称,第二个参数是操作类型 let newItem = { id: 1, name: '徐嘻嘻', age: 3, sex: 'female' }; let transaction = db.transaction('dataBaseName', "readwrite"); // 找到对应的存储对象 let objectStore = transaction.objectStore('person'); // 添加到数据对象中, 传入JAVAscript对象 objectStore.add(newItem);
// 这里的 db 就是第二步中的 db 对象, // 新建事务 let transaction = db.transaction('dataBaseName', "readwrite"); // 新数据主体 let newRecord = { id: 1, name: '徐嘎嘎', age: 5, sex: 'male' }; // 打开已经存储的数据对象 let objectStore = transaction.objectStore('person'); // 获取存储的对应键的存储对象, 传入主键 id,值为 1 let objectStoreRequest = objectStore.get(1); // 获取成功后替换当前数据 objectStoreRequest.onsuccess = function(event) { // 数据 var record = objectStoreRequest.result; // 遍历替换 for (let key in newRecord) { if (typeof record[key] != 'undefined' || key !== 'id') { record[key] = newRecord[key]; } } // 更新数据库存储数据 objectStore.put(record); };
// 这里的 db 就是第二步中的 db 对象, // 新建事务 let transaction = db.transaction('dataBaseName', "readwrite"); // 打开已经存储的数据对象 let objectStore = transaction.objectStore('person'); // 获取存储的对应键的存储对象, 传入主键 id,值为 1 let objectStoreRequest = objectStore.delete(1);
可以提效的类库
从上面的例子中可以看出,每一次操作需要至少三行代码才能完成,而且需要一直维护 DB 的对象引用,避免它被回收,这样子开发代码膨胀得太厉害,所以我们在业务中引入其他类库来减少代码量
这两个类库比较符合我们的开发要求,我们当前使用的是 LocalForage。
结束语
在业务开发中,我们都会碰到或多或少的本地存储需求,本文介绍了其中一种存储方案 IndexedDB 的简单实践。就我们的应用场景来看,IndexedDB 的适用面还是很广的。考虑到 IE10 也可以支持,把它实践在实际项目中应该是没有问题的。
文章首发于:https://www.zoo.team/article/indexeddb