使用場景,使用者狀态管理
1.存儲大小限制 僅4k左右,且每次請求都會發送回伺服器
2.單域名數量限制 50個左右
3.污染請求頭,浪費流量
二、localStorage 和 sessionStorage
用法
1.使用setItem方法設定存儲内容
2.使用getItem方法擷取存儲内容
3.使用removeItem方法删除存儲内容
4.使用clear方法清除所有内容
5.使用length屬性擷取存儲内容的個數
6.使用key方法擷取存儲字段
localStorage持久化,不會随着浏覽器的關閉而失效,存儲在硬碟中, 2.5MB 到 10MB 之間(各家浏覽器不同)。可以設定資料的存儲時間,過期資料清理,自行維護存儲空間。不提供搜尋功能,不能建立自定義的索引。
sessionStorage會随着網頁會話結束而失效,存儲在記憶體中。存儲流量不一,部分浏覽器不設限。
注意點
1.注意存儲容量超出配額 超出後會抛出異常
2.存儲類型的限制,僅能存儲字元串 隐式的類型轉換
3.sessionStorage失效機制
-重新整理頁面不會失效
-同一個域名下的不同标簽不共享
三、indexedDB資料庫
IndexedDB 就是浏覽器提供的本地資料庫,它可以被網頁腳本建立和操作。IndexedDB 允許儲存大量資料,提供查找接口,還能建立索引。這些都是 LocalStorage 所不具備的。就資料庫類型而言,IndexedDB 不屬于關系型資料庫(不支援 SQL 查詢語句),更接近 NoSQL 資料庫。
特點
(1)鍵值對儲存。 IndexedDB 内部采用對象倉庫(object store)存放資料。所有類型的資料都可以直接存入,包括 JavaScript 對象。對象倉庫中,資料以"鍵值對"的形式儲存,每一個資料記錄都有對應的主鍵,主鍵是獨一無二的,不能有重複,否則會抛出一個錯誤。
(2)異步。 IndexedDB 操作時不會鎖死浏覽器,使用者依然可以進行其他操作,這與 LocalStorage 形成對比,後者的操作是同步的。異步設計是為了防止大量資料的讀寫,拖慢網頁的表現。
(3)支援事務。 IndexedDB 支援事務(transaction),這意味着一系列操作步驟之中,隻要有一步失敗,整個事務就都取消,資料庫復原到事務發生之前的狀态,不存在隻改寫一部分資料的情況。
(4)同源限制。 IndexedDB 受到同源限制,每一個資料庫對應建立它的域名。網頁隻能通路自身域名下的資料庫,而不能通路跨域的資料庫。
(5)儲存空間大。 IndexedDB 的儲存空間比 LocalStorage 大得多,一般來說不少于 250MB,甚至沒有上限。
(6)支援二進制儲存。 IndexedDB 不僅可以儲存字元串,還可以儲存二進制資料(ArrayBuffer 對象和 Blob 對象)。
對象接口關系
關系圖.png
簡單事例
以資料庫dataObj為例,建立一個person倉庫,索引為name
1、打開或建立一個資料庫
// 相容性寫法
window.indexedDB =
window.indexedDB ||
window.mozIndexedDB ||
window.webkitIndexedDB ||
window.msIndexedDB;
window.IDBTransaction =
window.IDBTransaction ||
window.webkitIDBTransaction ||
window.msIDBTransaction;
window.IDBKeyRange =
window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
// 相容性寫法
//打開或者建立資料庫,如果資料庫存在的時候就是打開,不存在的時候就是建立
//傳入資料庫的名稱和版本号,版本号為整數如果省略,打開已有資料庫時,預設為目前版本;建立資料庫時,預設為1
//這是一個異步操作,但是會立刻傳回一個 IDBOpenDBRequest 對象。
var request = window.indexedDB.open('dateObj', 1);
//删除資料庫,調用deleteDatabase()方法以後,目前資料庫的其他已經打開的連接配接都會接收到versionchange事件。
// window.indexedDB.deleteDatabase(databaseName);
// 建立資料庫與打開資料庫是同一個操作。如果指定的資料庫不存在,就會建立。
// 不同之處在于,後續的操作主要在upgradeneeded事件的監聽函數裡面完成,因為這時版本從無到有,是以會觸發這個事件。
var db;//資料庫IDBDatabase對象
request.onupgradeneeded = function (event) {
console.log('建立資料庫')
db = event.target.result;
var objectStore;
if (!db.objectStoreNames.contains('person')) { //檢查資料庫是否包含該對象倉庫
// 隻能在onupgradeneeded回調函數中建立存儲空間,而不能在資料庫打開後的success回調函數中建立。
// 删除倉庫對象(删除表格) db.deleteObjectStore(objectStoreName);
// db.close():關閉資料庫連接配接,實際會等所有事務完成後再關閉。
objectStore = db.createObjectStore('person', {
keyPath: 'id', //keyPath表示主鍵,(由于主鍵的值不能重複,是以上例存入之前,必須保證資料的email屬性值都是不一樣的),預設值為null
autoIncrement: true
//autoIncrement屬性表示,是否使用自動遞增的整數作為主鍵(第一個資料記錄為1,第二個資料記錄為2,以此類推),預設為false。
//一般來說,keyPath和autoIncrement屬性隻要使用一個就夠了,如果兩個同時使用,表示主鍵為遞增的整數,且對象不得缺少keyPath指定的屬性。
});
// IDBObject.createIndex()的三個參數分别為索引名稱、指定根據存儲資料的哪一個屬性來建構索引、配置對象(說明該屬性是否包含重複的值)。
//建立索引
objectStore.createIndex('name', 'name', {
unique: false//true的話表示不允許有重複的值
});
// 删除索引:objectStore.deleteIndex()
// 擷取所有索引對象:objectStore.index()
}
// 如果指定的版本号,大于資料庫的實際版本号,就會發生資料庫更新事件upgradeneeded
request.onupgradeneeded = function (event) {
db = event.target.result;
}
//失敗事件
request.onerror = function (event) {
console.log('資料庫打開報錯');
};
//成功事件
request.onsuccess = function (event) {
db = event.target.result;
//無論是建立還是打開資料庫,最後都會進入onsuccess
console.log('資料庫打開成功');
};
}
2、向person對象倉庫寫入資料記錄
function add(db, name) {
// 事務函數transaction的第一個參數為需要關聯的存儲空間,第二個可選參數為事務模式。
// readonly(隻讀)和readwrite(讀寫)。添加資料使用readwrite,讀取資料使用readonly。
// 第二個參數是可選的,省略時預設為readonly模式。
console.log('db', db.transaction(['person'], 'readwrite'))
var req = db.transaction(['person'], 'readwrite').objectStore('person').add({
name: name,
age: 29,
email: '[email protected]'
});
req.onsuccess = function (event) {
console.log('db', db)
console.log('資料寫入成功');
};
req.onerror = function (event) {
console.log('event', event)
console.log('資料寫入失敗');
}
}
3、在person對象倉庫讀取資料記錄
function read(db) {//讀取一條
var transaction = db.transaction(['person']);
var objectStore = transaction.objectStore('person');
var request = objectStore.get(1);//用主id去擷取到對應的值
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('未獲得資料記錄');
}
};
}
//使用索引擷取到具體的值
function readItem(db, name) {
var store = db.transaction(['person'], 'readonly')
.objectStore('person')
var index = store.index('name')
// var request=index.count(name)//符合索引的值的數量
// var request=index.get(name)//隻能擷取到第一個比對到的值
// var request=index.getAll(name)//擷取到所有比對到的值
// var request=index.getKey(name)//擷取到第一個比對到的值的主鍵的值
// var request=index.getAllKeys(name)//擷取到所有比對到的值的主鍵的值
var request = index.openCursor(name)
request.onsuccess = function (e) {
var result = e.target.result
console.log('result', result)
};
}
function readAll(db) {//讀取全部
var objectStore = db.transaction('person').objectStore('person');
// objectStore.openCursor()用于擷取一個指針對象。
// objectStore.openKeyCursor()用于擷取一個主鍵指針對象。
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('沒有更多資料了!');
}
};
}
4、在person對象倉庫更新資料記錄
function update(db) {
var request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.put({
id: 1,
name: '李四',
age: 35,
email: '[email protected]'
});
request.onsuccess = function (event) {
console.log('資料更新成功');
};
request.onerror = function (event) {
console.log('資料更新失敗');
}
}
5、在person對象倉庫删除資料記錄
function remove(db) {
var request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.delete(1);
request.onsuccess = function (event) {
console.log('資料删除成功');
};
}
四、參考文章