本地存储就是指在浏览器中存储数据,是相对于服务器中存储数据来讲的。html
浏览器的本地存储主要包括4种方式: Cookie、Storage、SQL数据库和IndexedDB。前端
Cookie提出来得最先,其最初得设计目的只是为了保存用户得登陆信息,因此并不适合保存大量数据。Cookie容量小,将保存得数据拼接成字符串得形式跟程序进行操做。没打开一个网址,浏览器都会将该网站下得全部Cookie数据所有传到服务器端,由于其最初得设计目的只是用来保护用户的登陆信息(例如SessionId)。web
Sotrage是HTML5种用于存储本地数据的对象,由于其设计目的就是存储本地数据,因此其操做比Cookie灵活得多。Storage容量比Cookie大,能够直接按照键值对存储数据并使用健名获取数据。Storage分为sessionStorage和localStorage,前者在浏览器关闭后就会被清除,后者会一直存储在浏览器中,除非人为或代码清除。数据库
SQL数据库在浏览器中封装了一个小型得SQLLite数据库,可是从前端架构上并不适合使用。例如:JS对象得属性随时均可能发生改变,可能增删,也可能修改数据类型,可是SQL数据库要求在对数据操做以前就先肯定好数据的结构。数组
IndexedDB属于一种noSQL数据库,是非结构化的,它所保存的数据记录跟JS的对象同样能够随时变化属性(字段)。与Storage相比,它能够保存更多的数据,并且还可使用数据库的索引、事务等相关概念,可是使用起来要比Storage复杂很多。浏览器
Storage是window对象的一个function类型的属性对象,可是这个function对象比较特别,它既不能够看成方法来执行,也不能够用来建立实例对象,JS引擎会默认为建立两个Storage的实例对象,直接调用就能够了。
JS引擎建立的两个Storage实例对象分别是sessionStorage和localStorage,前者用于暂时保存,浏览器关闭后数据就会丢失;后者用于长久保存,及时关闭浏览器数据也不会丢失。
Storage.prototype:
操做数据的方法有:服务器
在控制台利用session storage setItem设置一个值后能够在Application的Session Storage查看:
微信
localStorage与sessionStorage在方法上使用相同,不一样之处就在存储后数据清除方式不一样。session
Storage实例对象修改数据的时候会触发一个StorageEvent事件,这个事件有些特别,当事件触发后,消息会发送到打开的全部当前网站的其余页面中(固然要在同一个浏览器中),至因而否会发送给当前页面,不一样的浏览器又不不一样的处理方法。(我的测试如下几个浏览器行为均相同,不发送给当前页面:谷歌浏览器(85.0.4183.83)、(Microsoft Edge 44.18362.449.0)、Firefox(78.0.2 (64 位))、双核浏览器(版本 1.0.4.2))
StorageEvent.prototype:
架构
代码示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <input value="Test Storage" type="button" id='button'/> <script> const btn = document.querySelector('#button'); btn.onclick = () => { localStorage.setItem('testKey', 'testValue1'); } window.addEventListener('storage', function(e){ console.log(`key: ${e.key}`); console.log(`oldValue: ${e.oldValue}`); console.log(`newValue: ${e.newValue}`); console.log(`url: ${e.url}`); console.log(`is localStorage: ${e.storageArea === localStorage}`); }); </script> </body> </html>
IndexedDB数据库是一种noSQL数据库,可是其所用到的概念大部分跟SQL数据库相似,固然也存在不彻底相同的地方。不一样之处仅在于IndexedDB数据库不是将对象转换为记录,而后再保存到表里面,而是直接保存的对象,它是经过“ID->数据对象”这种模式来保存的。
跟IndexedDB数据库相关的对象主要包括11个对象:IDBFactory、IDBDatabase、IDBObjectStore、IDBIndex、IDBKeyRange、IDBCursor、IDBCursorWithValue、IDBTransaction、IDBVersionChangeEvent、IDBOpenDBRequest和IDBRequest。
这11个对象都是window的function类型的属性对象,使用时都使用其示例,但不须要用户本身使用new来建立,在须要的时候就能够自动获取。11个对象能够分为4类:数据库和ObjecStore相关对象、数据相关对象、查询相关对象和辅助对象。气筒辅助对象包括IDBVersionChangeEvent、IDBOpenDBRequest和IDBRequest。
语法:
const db_worker = indexedDB.open('dbName', dbVersion);
示例:
<script> const workerDBRequest = indexedDB.open('database', 1); workerDBRequest.onerror = function(event) { console.log('打开数据库失败'); } workerDBRequest.onsuccess = function(event) { db_worker = workerDBRequest.result; // 也可使用event.target.result console.log('打开成功'); } </script>
createObjectStore方法有两个参数,第一个参数是所要建立的ObjectSore的名字,第二个参数是一个对象,用于描述ID,该对象能够有两个属性:keyPath和autoIncrement,前者用来指定一个对象中的属性用做ID,后者若为true则会在保存数据时用Generator生成一个ID,可是这里须要本身建立一个Generator。
示例以下:
<script> const workerDBRequest = indexedDB.open('worker', 2); workerDBRequest.onerror = function(event) { console.log('打开数据库失败'); } workerDBRequest.onsuccess = function(event) { db_worker = workerDBRequest.result; // 也可使用event.target.result console.log('打开数据库成功'); } workerDBRequest.onupgradeneeded = function(e) { var db = workerDBRequest.result; db.createObjectStore('category', {}); console.log(`${db.name} 的版本号修改成了${db.version}`); } </script>
数据相关操做除了前面介绍的以外,主要还要用到表示事务的IDBTransaction对象。
数据库(IDBDatabse的实例对象)的绝大多数操做都须要用事务来完成,数据库实例对象包含一个transaction方法属性(其实时IDBDatabase.prototype的属性),调用该属性方法就能够建立事务。transaction方法有两个参数,第一个参数用于指定要操做的ObjectStore,能够是一个,也能够是多个,多个采用数组传递;第二个参数指定事务的类型,能够是readonly(默认)或者readwrite,分别表示建立只读或读写事务。
[“objectStoreNames”, “mode”, “db”, “error”, “onabort”, “oncomplete”, “onerror”, “objectStore”, “commit”, “abort”, “durability”, “constructor”]
[“name”, “keyPath”, “indexNames”, “transaction”, “autoIncrement”, “put”, “add”, “delete”, “clear”, “get”, “getKey”, “getAll”, “getAllKeys”, “count”, “openCursor”, “openKeyCursor”, “index”, “createIndex”, “deleteIndex”, “constructor”]
示例:
<script> const workerDBRequest = indexedDB.open('worker', 3); workerDBRequest.onerror = function(event) { console.log('打开数据库失败'); } workerDBRequest.onupgradeneeded = function(e) { var db = workerDBRequest.result; db.createObjectStore('category', {keyPath: 'id'}); console.log(`${db.name} 的版本号修改成了${db.version}`); } workerDBRequest.onsuccess = function(event) { db_worker = workerDBRequest.result; // 也可使用event.target.result console.log('打开数据库成功'); workerDBOpenSuccess(); } function workerDBOpenSuccess() { const tx_category = db_worker.transaction('category', 'readwrite'); const store_category = tx_category.objectStore('category'); const category1 = {'id':007, 'name':'zzh', 'age':18}; const categoryAddRequest = store_category.add(category1); categoryAddRequest.onsuccess = function(event) { console.log('保存成功'); } categoryAddRequest.onerror = function(evevt) { console.log('保存失败'); } } </script>
实例:
<script> const workerDBRequest = indexedDB.open('worker', 3); workerDBRequest.onerror = function(event) { console.log('打开数据库失败'); } workerDBRequest.onupgradeneeded = function(e) { var db = workerDBRequest.result; db.createObjectStore('category', {keyPath: 'id'}); console.log(`${db.name} 的版本号修改成了${db.version}`); } workerDBRequest.onsuccess = function(event) { db_worker = workerDBRequest.result; // 也可使用event.target.result console.log('打开数据库成功'); workerDBOpenSuccess(); } function workerDBOpenSuccess() { const tx_category = db_worker.transaction('category', 'readwrite'); const store_category = tx_category.objectStore('category'); const categoryGetRequest = store_category.get(7); categoryGetRequest.onsuccess = function (event) { console.log(`查询成功: ${JSON.stringify(categoryGetRequest.result)}`); } } </script>
查询的方式还有不少种,就像关系型数据库同样,查询能够根据不一样的条件筛选数据。
<script> const workerDBRequest = indexedDB.open('worker', 3); workerDBRequest.onerror = function (event) { console.log('打开数据库失败'); } workerDBRequest.onupgradeneeded = function (e) { var db = workerDBRequest.result; db.createObjectStore('category', { keyPath: 'id' }); console.log(`${db.name} 的版本号修改成了${db.version}`); } workerDBRequest.onsuccess = function (event) { db_worker = workerDBRequest.result; // 也可使用event.target.result console.log('打开数据库成功'); workerDBOpenSuccess(); } function workerDBOpenSuccess() { const tx_category = db_worker.transaction('category', 'readwrite'); const store_category = tx_category.objectStore('category'); const categoryGetRequest = store_category.get(7); categoryGetRequest.onsuccess = function (event) { console.log(`查询成功: ${JSON.stringify(categoryGetRequest.result)}`); let data = event.target.result; data.age = 19; const categoryPutRequest = store_category.put(data); categoryPutRequest.onsuccess = function (event) { console.log('更新成功'); } } } </script>
IndexedDB可能不会实时更新显示,有时须要刷新后查看,实际值已经修改。
示例:
<script> const workerDBRequest = indexedDB.open('worker', 3); workerDBRequest.onerror = function (event) { console.log('打开数据库失败'); } workerDBRequest.onupgradeneeded = function (e) { var db = workerDBRequest.result; db.createObjectStore('category', { keyPath: 'id' }); console.log(`${db.name} 的版本号修改成了${db.version}`); } workerDBRequest.onsuccess = function (event) { db_worker = workerDBRequest.result; // 也可使用event.target.result console.log('打开数据库成功'); workerDBOpenSuccess(); } function workerDBOpenSuccess() { const tx_category = db_worker.transaction('category', 'readwrite'); const store_category = tx_category.objectStore('category'); const categoryDeleteRequest = store_category.delete(7); // 根据id删除 categoryDeleteRequest.onsuccess = function(event) { console.log('删除成功'); } } </script>
显示须要刷新后查看。
IndexedDB的操做还有不少,首先大概理解下noSQL的原理,而后再对这些对象,以及对象可进行的操做进行理解使用。感兴趣的也能够参看MDN详解:https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API/Using_IndexedDB
若是文章可以对您有所帮助,我便感到十分荣幸。如若文章能被您点赞,那即是万分荣幸。
我的微信:iotzzh 公众号:前端微说 我的网站:www.iotzzh.com