说到前端的本地存储方案,LocalStorage,sessionStorage 和cookie 不得不说,但是这里方案或多或少都有限制,对于不同的浏览器,他们的存储量通常不超过10M,因此碰到大量的数据存储,需要一个合适的本地存储方案,这就是indexedDB诞生的背景
indexedDB的特点:
1. 事务性数据库: 事务性意味着,只有所有操作都成功的情况下,数据存储或者修改才能执行,否则回滚到修改前的状态
2.异步:indexedDB 的操作是异步的,异步操作在执行数据读写时不会锁死浏览器,用户同时可以执行其他操作
3.支持多种形式文件存储: indexedDB不仅仅可以存储字符串,也可以存储二进制,图片等文件。
4.同源限制:IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
5.储存空间大:indexedDB的存储空间不少于250MB,甚至没有上限
indexedDB的兼容性: 兼容性相关的可以看这里 https://caniuse.com/?search=IndexedDB
使用:
1 打开(建立数据库),使用indexedDB.open()
方法
var request = window.indexedDB.open(databaseName, version);
这个方法接受两个参数,第一个参数是字符串,表示数据库的名字。如果指定的数据库不存在,就会新建数据库。第二个参数是整数,表示数据库的版本。如果省略,打开已有数据库时,默认为当前版本;新建数据库时,默认为1
。
indexedDB.open()
方法返回一个 IDBRequest 对象。这个对象通过三种事件error
、success
、upgradeneeded
,处理打开数据库的操作结果。
var db;
request.onerror = function (event) {
console.log('数据库打开报错');
};
request.onsuccess = function (event) {
db = request.result; console.log('数据库打开成功');
};
request.onupgradeneeded = function (event) {
db = event.target.result;
}
这里要注意,新建一个数据库 会触发 onupgradeneeded 方法,而打开则会触发 onsuccess 方法,基于不同方法需要进行不同的处理逻辑,大家使用的时候要注意
2 建表
request.onupgradeneeded = function (event) { db = event.target.result; var objectStore; if (!db.objectStoreNames.contains('person')) { objectStore = db.createObjectStore('person', { keyPath: 'id' }); } }
这里新建一张为person的表,主键为id
还可以自动生成主键
var objectStore = db.createObjectStore( 'person', { autoIncrement: true } );
新建对象仓库之后,还需要新增索引
request.onupgradeneeded = function(event) { db = event.target.result; var objectStore = db.createObjectStore('person', { keyPath: 'id' }); objectStore.createIndex('name', 'name', { unique: false }); objectStore.createIndex('email', 'email', { unique: true }); }
上面代码中,IDBObject.createIndex()
的三个参数分别为索引名称、索引所在的属性、配置对象(说明该属性是否包含重复的值)。
3.插入数据
function add() { var request = db.transaction(['person'], 'readwrite') .objectStore('person') .add({ id: 1, name: '张三', age: 24, email: 'zhangsan@example.com' }); request.onsuccess = function (event) { console.log('数据写入成功'); }; request.onerror = function (event) { console.log('数据写入失败'); } } add();
4.读取数据
function read() { var transaction = db.transaction(['person']); var objectStore = transaction.objectStore('person'); var request = objectStore.get(1); request.onerror = function(event) { console.log('事务失败'); }; request.onsuccess = function( event) { if (request.result) { console.log('Name: ' + request.result.name); console.log('Age: ' + request.result.age); console.log('Email: ' + request.result.email); } else { console.log('未获得数据记录'); } }; } read();
5.遍历数据
function readAll() { var objectStore = db.transaction('person').objectStore('person'); objectStore.openCursor().onsuccess = function (event) { var cursor = event.target.result; if (cursor) { console.log('Id: ' + cursor.key); console.log('Name: ' + cursor.value.name); console.log('Age: ' + cursor.value.age); console.log('Email: ' + cursor.value.email); cursor.continue(); } else { console.log('没有更多数据了!'); } }; } readAll();
6.更新数据
function update() { var request = db.transaction(['person'], 'readwrite') .objectStore('person') .put({ id: 1, name: '李四', age: 35, email: 'lisi@example.com' }); request.onsuccess = function (event) { console.log('数据更新成功'); }; request.onerror = function (event) { console.log('数据更新失败'); } } update();
7.删除数据
function remove() { var request = db.transaction(['person'], 'readwrite') .objectStore('person') .delete(1); request.onsuccess = function (event) { console.log('数据删除成功'); }; } remove();
8.使用索引
索引的意义在于,可以让你搜索任意字段,也就是说从任意字段拿到数据记录。如果不建立索引,默认只能搜索主键(即从主键取值)。
var transaction = db.transaction(['person'], 'readonly'); var store = transaction.objectStore('person'); var index = store.index('name'); var request = index.get('李四'); request.onsuccess = function (e) { var result = e.target.result; if (result) { // ... } else { // ... } }
这里我封装了一个方法供大家使用
1 /** 2 * @description: indexDB 在使用的时候,直接生产库,然后查看是否有表,有表添加数据或者修改数据,没有表就进行新增 3 * @param databaseName => 数据库名字 4 * @param table => 数据库表名字 5 * @param key => 存储时候的键(indexDB是根据键值进行查询) 6 * @param data => 进行新增的数据或者说是修改的数据,具体看调用方法 7 * @param callback => 回调函数(indexDB是异步的,所以大部分都用回调或者Promise去执行) 8 * @return {type} 9 */ 10 if (!window.localStorage.getItem('version')) { 11 window.localStorage.setItem('version', 1) 12 } 13 let indexDataBase = { 14 init: (databaseName, table, flags, callback) => { 15 let flag = flags; 16 let verIndex = window.localStorage.getItem('version') 17 var request = window.indexedDB.open(databaseName, verIndex); 18 request.onerror = () => { 19 let errdata = { 20 status: 'error', 21 mes: '打开数据库失败!' 22 } 23 callback(errdata) 24 }; 25 var indexdb; 26 request.onsuccess = (event) => { 27 indexdb = event.target.result; 28 if (flag == true) { 29 verIndex = parseInt(window.localStorage.getItem('version')) + 1 30 window.localStorage.setItem('version', verIndex); 31 } else { 32 verIndex = parseInt(window.localStorage.getItem('version')) 33 } 34 if (indexdb.objectStoreNames.length > 0) { 35 flag = true 36 } 37 indexdb.isCreate = flag; 38 flag = false; 39 callback(indexdb) 40 }; 41 request.onupgradeneeded = (event) => { 42 indexdb = event.target.result; 43 if (!indexdb.objectStoreNames.contains(table)) { 44 if (flag) { 45 indexdb.createObjectStore(table, { 46 keyPath: 'id' 47 }); 48 } 49 } 50 } 51 }, 52 insertData: (databaseName, table, key, data, callback) => { 53 dexie.init(databaseName, table, true, (db) => { 54 try { 55 var addData = [{ 56 id: key, 57 value: data 58 }] 59 var transaction = db.transaction(table, 'readwrite'); 60 var store = transaction.objectStore(table); 61 for (var i = 0; i < addData.length; i++) { 62 store.add(addData[i]); 63 } 64 let backData = { 65 status: 'success', 66 dataBase: databaseName, 67 table: table, 68 data: addData 69 } 70 callback(backData) 71 } catch (error) { 72 let errdata = { 73 status: 'error', 74 mes: '数据写入失败!' 75 } 76 callback(errdata) 77 } 78 db.close() 79 }) 80 }, 81 selectData: (databaseName, table, key, callback) => { 82 dexie.init(databaseName, table, false, (db) => { 83 if (db.isCreate == false) { 84 let errdata = { 85 status: 'error', 86 mes: '获取数据失败!' 87 } 88 callback(errdata) 89 db.close() 90 return 91 } else { 92 var transaction = db.transaction(table, 'readwrite'); 93 var store = transaction.objectStore(table); 94 var request = store.get(key); 95 request.onsuccess = (e) => { 96 try { 97 var resultData = e.target.result; 98 let backData = { 99 status: 'success', 100 dataBase: databaseName, 101 table: table, 102 data: resultData.value 103 } 104 callback(backData) 105 } catch (error) { 106 let errdata = { 107 status: 'error', 108 mes: '数据读取失败!数据库中没有该数据!' 109 } 110 callback(errdata) 111 } 112 }; 113 request.onerror = () => { 114 let errdata = { 115 status: 'error', 116 mes: '数据读取失败!' 117 } 118 callback(errdata) 119 } 120 } 121 db.close() 122 }) 123 }, 124 deleteData: (databaseName, table, key, callback) => { 125 dexie.init(databaseName, table, false, (db) => { 126 if (db.isCreate == false) { 127 let errdata = { 128 status: 'error', 129 mes: '删除数据失败!' 130 } 131 callback(errdata) 132 db.close() 133 return 134 } else { 135 var transaction = db.transaction(table, 'readwrite'); 136 var store = transaction.objectStore(table); 137 138 var getresult = store.get(key); 139 let pro = new Promise((resolved) => { 140 getresult.onsuccess = (e) => { 141 resolved(e.target.result) 142 db.close() 143 } 144 }) 145 pro.then(res => { 146 var result = store.delete(key); 147 if (res != undefined) { 148 result.onsuccess = () => { 149 let errdata = { 150 status: 'success', 151 mes: '删除成功!', 152 } 153 callback(errdata) 154 } 155 result.onerror = () => { 156 let errdata = { 157 status: 'error', 158 mes: '删除失败!' 159 } 160 callback(errdata) 161 } 162 } else { 163 let errdata = { 164 status: 'error', 165 mes: '数据库中已经没有该数据!' 166 } 167 callback(errdata) 168 } 169 db.close() 170 }) 171 } 172 }) 173 }, 174 changeData: (databaseName, table, key, data, callback) => { 175 dexie.init(databaseName, table, true, (db) => { 176 try { 177 var addData = { 178 id: key, 179 value: data 180 } 181 var transaction = db.transaction(table, 'readwrite'); 182 var store = transaction.objectStore(table); 183 store.put(addData); 184 let backData = { 185 status: 'success', 186 dataBase: databaseName, 187 table: table, 188 data: addData 189 } 190 callback(backData) 191 } catch (error) { 192 let errdata = { 193 status: 'error', 194 mes: '更新写入失败!' 195 } 196 callback(errdata) 197 } 198 db.close() 199 }) 200 }, 201 clearTable: (databaseName, table, callback) => { 202 dexie.init(databaseName, table, true, (db) => { 203 var transaction = db.transaction(table, 'readwrite'); 204 var store = transaction.objectStore(table); 205 var result = store.clear(); 206 result.onsuccess = ()=> { 207 let successmsg = { 208 status: "success", 209 msg: "数据表" + table + "清空成功!", 210 } 211 callback(successmsg) 212 } 213 result.onerror = () => { 214 let successmsg = { 215 status: "success", 216 msg: "数据表" + table + "清空失败!", 217 } 218 callback(successmsg) 219 } 220 }) 221 }, 222 dexie: () => { 223 224 } 225 } 226 227 export default indexDataBase
再见!