javascript
js清空本地存储_JS原理、方法与实践 本地存储
本地存儲就是指在瀏覽器中存儲數(shù)據(jù),是相對于服務(wù)器中存儲數(shù)據(jù)來說的。
1. 本地存儲的分類
瀏覽器的本地存儲主要包括4種方式:Cookie、Storage、SQL數(shù)據(jù)庫和IndexedDB。
Cookie
Cookie提出來得最早,其最初的設(shè)計(jì)目的只是為了保存用戶的登錄信息,所以并不適合保存大量數(shù)據(jù)。Cookie容量小,將保存的數(shù)據(jù)拼接成字符串的形式跟程序進(jìn)行操作。沒打開一個(gè)網(wǎng)址,瀏覽器都會(huì)將該網(wǎng)站下的所有Cookie數(shù)據(jù)全部傳到服務(wù)器端,因?yàn)槠渥畛醯脑O(shè)計(jì)目的只是用來保護(hù)用戶的登錄信息(例如SessionId)。
Storage
Sotrage是HTML5中用于存儲本地?cái)?shù)據(jù)的對象,因?yàn)槠湓O(shè)計(jì)目的就是存儲本地?cái)?shù)據(jù),所以其操作比Cookie靈活得多。Storage容量比Cookie大,可以直接按照鍵值對存儲數(shù)據(jù)并使用鍵名獲取數(shù)據(jù)。Storage分為sessionStorage和localStorage,前者在瀏覽器關(guān)閉后就會(huì)被清除,后者會(huì)一直存儲在瀏覽器中,除非人為或代碼清除。
SQL數(shù)據(jù)庫
SQL數(shù)據(jù)庫在瀏覽器中封裝了一個(gè)小型的SQLLite數(shù)據(jù)庫,但是從前端架構(gòu)上并不適合使用。例如:JS對象的屬性隨時(shí)都可能發(fā)生改變,可能增刪,也可能修改數(shù)據(jù)類型,但是SQL數(shù)據(jù)庫要求在對數(shù)據(jù)操作之前就先確定好數(shù)據(jù)的結(jié)構(gòu)。
IndexedDB
IndexedDB屬于一種noSQL數(shù)據(jù)庫,是非結(jié)構(gòu)化的,它所保存的數(shù)據(jù)記錄跟JS的對象一樣可以隨時(shí)變化屬性(字段)。與Storage相比,它可以保存更多的數(shù)據(jù),而且還可以使用數(shù)據(jù)庫的索引、事務(wù)等相關(guān)概念,但是使用起來要比Storage復(fù)雜不少。
2. Storage存儲
Storage是window對象的一個(gè)function類型的屬性對象,但是這個(gè)function對象比較特別,它既不可以當(dāng)作方法來執(zhí)行,也不可以用來創(chuàng)建實(shí)例對象,JS引擎會(huì)默認(rèn)為創(chuàng)建兩個(gè)Storage的實(shí)例對象,直接調(diào)用就可以了。JS引擎創(chuàng)建的兩個(gè)Storage實(shí)例對象分別是sessionStorage和localStorage,前者用于暫時(shí)保存,瀏覽器關(guān)閉后數(shù)據(jù)就會(huì)丟失;后者用于長久保存,及時(shí)關(guān)閉瀏覽器數(shù)據(jù)也不會(huì)丟失。Storage.prototype:??操作數(shù)據(jù)的方法有:
getItem(key)
setItem(key, value)
removeItem(key)
clear()
在控制臺利用session storage setItem設(shè)置一個(gè)值后可以在Application的Session Storage查看:??
localStorage與sessionStorage在方法上使用相同,不同之處就在存儲后數(shù)據(jù)清除方式不同。
3. StorageEvent
Storage實(shí)例對象修改數(shù)據(jù)的時(shí)候會(huì)觸發(fā)一個(gè)StorageEvent事件,這個(gè)事件有些特別,當(dāng)事件觸發(fā)后,消息會(huì)發(fā)送到打開的所有當(dāng)前網(wǎng)站的其他頁面中(當(dāng)然要在同一個(gè)瀏覽器中),至于是否會(huì)發(fā)送給當(dāng)前頁面,不同的瀏覽器有不不同的處理方法。(個(gè)人測試以下幾個(gè)瀏覽器行為均相同,不發(fā)送給當(dāng)前頁面:谷歌瀏覽器(85.0.4183.83)、(Microsoft Edge 44.18362.449.0)、Firefox(78.0.2 (64 位))、雙核瀏覽器(版本 1.0.4.2)) StorageEvent.prototype:?
代碼示例:
lang="en">
charset="UTF-8">
name="viewport" content="width=device-width, initial-scale=1.0">
Document
value="Test Storage" type="button" id='button'/>
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}`);
});
4. IndexedDB 數(shù)據(jù)庫簡介
IndexedDB數(shù)據(jù)庫是一種noSQL數(shù)據(jù)庫,但是其所用到的概念大部分跟SQL數(shù)據(jù)庫類似,當(dāng)然也存在不完全相同的地方。不同之處僅在于IndexedDB數(shù)據(jù)庫不是將對象轉(zhuǎn)換為記錄,然后再保存到表里面,而是直接保存的對象,它是通過“ID->數(shù)據(jù)對象”這種模式來保存的。
IndexedDB數(shù)據(jù)庫操作
跟IndexedDB數(shù)據(jù)庫相關(guān)的對象主要包括11個(gè)對象:IDBFactory、IDBDatabase、IDBObjectStore、IDBIndex、IDBKeyRange、IDBCursor、IDBCursorWithValue、IDBTransaction、IDBVersionChangeEvent、IDBOpenDBRequest和IDBRequest。這11個(gè)對象都是window的function類型的屬性對象,使用時(shí)都使用其示例,但不需要用戶自己使用new來創(chuàng)建,在需要的時(shí)候就可以自動(dòng)獲取。11個(gè)對象可以分為4類:數(shù)據(jù)庫和ObjecStore相關(guān)對象、數(shù)據(jù)相關(guān)對象、查詢相關(guān)對象和輔助對象。氣筒輔助對象包括IDBVersionChangeEvent、IDBOpenDBRequest和IDBRequest。
數(shù)據(jù)庫和ObjectStore相關(guān)操作
創(chuàng)建/打開數(shù)據(jù)庫 IndexedDB數(shù)據(jù)庫的操作是基于事件的,或者說是異步處理的。open方法返回的是一個(gè)IDBOpenDBRequest的實(shí)力對象,常用屬性有onsuccess、onerror、onupgradeneeded,分別表示打開成功、打開失敗和數(shù)據(jù)庫版本升級。
語法:
const db_worker = indexedDB.open('dbName', dbVersion);
示例:
const workerDBRequest = indexedDB.open('database', 1);
workerDBRequest.onerror = function(event) {
console.log('打開數(shù)據(jù)庫失敗');
}
workerDBRequest.onsuccess = function(event) {
db_worker = workerDBRequest.result; // 也可以使用event.target.result
console.log('打開成功');
}
??
創(chuàng)建ObjectStore 通過上圖,我們可以看出, indexedDB.open(),返回的是一個(gè)IDBOpenDBRequest對象,IDBOpenDBRequest的result是一個(gè)IDBDatabase對象,有了這個(gè)對象,就可以創(chuàng)建ObjectStore了。這個(gè)result包含的屬性方法如下:??createObjectStore、deleteObjectStore分別用于創(chuàng)建和刪除ObjectStore。
注意:createObjectStore、deleteObjectStore只能在onupgradeneeded方法中執(zhí)行。
createObjectStore方法有兩個(gè)參數(shù),第一個(gè)參數(shù)是所要?jiǎng)?chuàng)建的ObjectSore的名字,第二個(gè)參數(shù)是一個(gè)對象,用于描述ID,該對象可以有兩個(gè)屬性:keyPath和autoIncrement,前者用來指定一個(gè)對象中的屬性用作ID,后者若為true則會(huì)在保存數(shù)據(jù)時(shí)用Generator生成一個(gè)ID,但是這里需要自己創(chuàng)建一個(gè)Generator。示例如下:
const workerDBRequest = indexedDB.open('worker', 2);
workerDBRequest.onerror = function(event) {
console.log('打開數(shù)據(jù)庫失敗');
}
workerDBRequest.onsuccess = function(event) {
db_worker = workerDBRequest.result; // 也可以使用event.target.result
console.log('打開數(shù)據(jù)庫成功');
}
workerDBRequest.onupgradeneeded = function(e) {
var db = workerDBRequest.result;
db.createObjectStore('category', {});
console.log(`${db.name} 的版本號修改為了${db.version}`);
}
數(shù)據(jù)操作相關(guān)
數(shù)據(jù)相關(guān)操作除了前面介紹的之外,主要還要用到表示事務(wù)的IDBTransaction對象。數(shù)據(jù)庫(IDBDatabse的實(shí)例對象)的絕大多數(shù)操作都需要用事務(wù)來完成,數(shù)據(jù)庫實(shí)例對象包含一個(gè)transaction方法屬性(其實(shí)是IDBDatabase.prototype的屬性),調(diào)用該屬性方法就可以創(chuàng)建事務(wù)。transaction方法有兩個(gè)參數(shù),第一個(gè)參數(shù)用于指定要操作的ObjectStore,可以是一個(gè),也可以是多個(gè),多個(gè)采用數(shù)組傳遞;第二個(gè)參數(shù)指定事務(wù)的類型,可以是readonly(默認(rèn))或者readwrite,分別表示創(chuàng)建只讀或讀寫事務(wù)。
IDBTransaction實(shí)例所包含的屬性:
["objectStoreNames", "mode", "db", "error", "onabort", "oncomplete", "onerror", "objectStore", "commit", "abort", "durability", "constructor"]?
IDBObjectStore實(shí)例包含的屬性:
["name", "keyPath", "indexNames", "transaction", "autoIncrement", "put", "add", "delete", "clear", "get", "getKey", "getAll", "getAllKeys", "count", "openCursor", "openKeyCursor", "index", "createIndex", "deleteIndex", "constructor"]?
增加數(shù)據(jù)
示例:
const workerDBRequest = indexedDB.open('worker', 3);
workerDBRequest.onerror = function(event) {
console.log('打開數(shù)據(jù)庫失敗');
}
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('打開數(shù)據(jù)庫成功');
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('保存失敗');
}
}
查詢數(shù)據(jù)
實(shí)例:
const workerDBRequest = indexedDB.open('worker', 3);
workerDBRequest.onerror = function(event) {
console.log('打開數(shù)據(jù)庫失敗');
}
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('打開數(shù)據(jù)庫成功');
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)}`);
}
}
?查詢的方式還有很多種,就像關(guān)系型數(shù)據(jù)庫一樣,查詢可以根據(jù)不同的條件篩選數(shù)據(jù)。
修改數(shù)據(jù)
const workerDBRequest = indexedDB.open('worker', 3);
workerDBRequest.onerror = function (event) {
console.log('打開數(shù)據(jù)庫失敗');
}
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('打開數(shù)據(jù)庫成功');
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('更新成功');
}
}
}
?IndexedDB可能不會(huì)實(shí)時(shí)更新顯示,有時(shí)需要刷新后查看,實(shí)際值已經(jīng)修改。?
刪除數(shù)據(jù)
示例:
const workerDBRequest = indexedDB.open('worker', 3);
workerDBRequest.onerror = function (event) {
console.log('打開數(shù)據(jù)庫失敗');
}
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('打開數(shù)據(jù)庫成功');
workerDBOpenSuccess();
}
function workerDBOpenSuccess() {
const tx_category = db_worker.transaction('category', 'readwrite');
const store_category = tx_category.objectStore('category');
const categoryDeleteRequest = store_category.delete(7); // 根據(jù)id刪除
categoryDeleteRequest.onsuccess = function(event) {
console.log('刪除成功');
}
}
顯示需要刷新后查看。?
IndexedDB的操作還有很多,首先大概理解下noSQL的原理,然后再對這些對象,以及對象可進(jìn)行的操作進(jìn)行理解使用。感興趣的也可以參看MDN詳解:https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDBAPI/UsingIndexedDB
掃二維碼|添加微信
掃碼關(guān)注
微信號|iotzzh
公眾號|前端微說
總結(jié)
以上是生活随笔為你收集整理的js清空本地存储_JS原理、方法与实践 本地存储的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 地菍的功效与作用、禁忌和食用方法
- 下一篇: 白色火龙果的功效与作用、禁忌和食用方法