localStorage/sessionStorage的優點前端
localStorage/sessionStorage的侷限web
IndexedDB 特色sql
IndexedDB vs Web Storage
Web Storage使用簡單字符串鍵值對在本地存儲數據,方便靈活,可是對於大量結構化數據存儲力不從心,IndexedDB是爲了可以在客戶端存儲大量的結構化數據,而且使用索引高效檢索的API。
IndexedDB的技術特色是,不須要你去寫特定的sql語句來對數據進行操做,它是nosql的,數據形式使用的是json。數據庫
IndexedDB裏數據以對象的形式存儲,每一個對象都有一個key值索引。IndexedDB裏的操做都是事務性的。一種對象存儲在一個objectStore裏,objectStore就至關於關係數據庫裏的表。IndexedDB能夠有不少objectStore,objectStore裏能夠有不少對象。每一個對象能夠用key值獲取。
IndexedDB vs LocalStoragejson
IndexedDB和LocalStorage都是用來在瀏覽器裏存儲數據,但它們使用不一樣的技術,有不一樣的用途,你須要根據本身的狀況適當的選擇使用哪一種。LocalStorage是用key-value鍵值模式存儲數據,但跟IndexedDB不同的是,它的數據並非按對象形式存儲。它存儲的數據都是字符串形式。若是你想讓LocalStorage存儲對象,你須要藉助JSON.stringify()能將對象變成字符串形式,再用JSON.parse()將字符串還原成對象。但若是要存儲大量的複雜的數據,這並非一種很好的方案。畢竟,localstorage就是專門爲小數量數據設計的,它的api是同步的。api
IndexedDB很適合存儲大量數據,它的API是異步調用的。IndexedDB使用索引存儲數據,各類數據庫操做放在事務中執行。IndexedDB甚至還支持簡單的數據類型。IndexedDB比localstorage強大得多,但它的API也相對複雜。數組
對於簡單的數據,你應該繼續使用localstorage,但當你但願存儲大量數據時,IndexedDB會明顯的更適合,IndexedDB能提供你更爲複雜的查詢數據的方式。瀏覽器
IndexedDB vs Web SQL
WebSQL也是一種在瀏覽器裏存儲數據的技術,跟IndexedDB不一樣的是,IndexedDB更像是一個NoSQL數據庫,而WebSQL更像是關係型數據庫,使用SQL查詢數據。W3C已經再也不支持這種技術。
由於再也不支持,因此你就不要在項目中使用這種技術了。cookie
IndexedDB vs Cookies
Cookies,每次HTTP接受和發送都會傳遞Cookies數據,它會佔用額外的流量。例如,若是你有一個10KB的Cookies數據,發送10次請求,那麼,總計就會有100KB的數據在網絡上傳輸。Cookies只能是字符串。瀏覽器裏存儲Cookies的空間有限,不少用戶禁止瀏覽器使用Cookies。因此,Cookies只能用來存儲小量的非關鍵的數據。網絡
(1)setItem(key,value):添加本地存儲數據。兩個參數,很是簡單就不說了。 (2)getItem(key):經過key獲取相應的Value。 (3)removeItem(key):經過key刪除本地數據。 (4)clear():清空數據。
建立、打開數據庫
須要根據不一樣瀏覽器的內核,建立indexedDB對象
var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB
打開一個數據庫,open方法, 該方法接收兩個參數:
var name = 'person-text', version = 1, db var request = indexedDB.open(name, version) request.onsuccess = function(event) { db = event.target.result; db.onsuccess = function(event) { console.log('數據庫操做成功!') }; db.onerror = function(event) { console.error('數據庫操做發生錯誤!', event.target.errorCode) }; console.log('打開數據庫成功!') } request.onerror = function(event) { console.error('建立數據庫出錯') console.error('error code:', event.target.errorCode) } request.onupgradeneeded = function(event) { // 更新對象存儲空間和索引 .... }
如果本域下不存在名爲 person-text 的數據庫,則上述代碼會建立一個名爲person-text、版本號爲1的數據庫; 觸發的事件依次爲: upgradeneeded、 success.
如果已存在名爲person-text的數據庫, 則上述代碼會打開該數據庫; 只觸發success/error事件,不會觸發upgradeneeded事件. db是對該數據庫的引用.
建立對象存儲空間和索引
在key-value型數據庫(如indexedDB)中, 一個數據庫會有多個對象存儲空間,每一個存儲空間有本身的主鍵、索引等;
建立對象存儲空間的操做通常放在建立數據庫成功回調裏:
request.onupgradeneeded = function(event) { // 更新對象存儲空間和索引 .... var database = event.target.result var objectStore = database.createObjectStore("person", { keyPath: "id" }) objectStore.createIndex('name', 'name', { unique: true }) objectStore.createIndex('age', 'age', { unique: false }) }
onupgradeneeded 是咱們惟一能夠修改數據庫結構的地方。在這裏面,咱們能夠建立和刪除對象存儲空間以及構建和刪除索引。
在數據庫對象database上,有如下方法可供調用:
數據操做(增刪改查)
對數據庫的操做(增刪查改等)都須要經過事務來完成,事務具備三種模式:
數據庫對象的transaction()方法接收兩個參數:
var transaction = db.transaction(['person'], 'readwrite') transaction.oncomplete = function(event) { console.log('事務完成!') } transaction.onerror = function(event) { console.log('事務失敗!', event.target.errorCode) } transaction.onabort = function(event) { console.log('事務回滾!') }
向數據庫中增長數據
經過事務對象transaction,在objectStore()方法中指定對象存儲空間,就獲得了能夠對該對象存儲空間進行操做的對象objectStore.
向數據庫中增長數據,add()方法增長的對象,如果數據庫中已存在相同的主鍵,或者惟一性索引的鍵值重複,則該條數據不會插入進去
var objectStore = transaction.objectStore('person') // 指定對象存儲空間 var data = [{"name": "張三", "age": "21", "sex": "男", "id": "11" }, {"name": "李四", "age": "19", "sex": "男", "id": "12" }, {"name": "王五", "age": "21", "sex": "女", "id": "13"}, {"name": "趙六", "age": "24", "sex": "男", "id": "14"}] data.forEach(function(item, index){ var request = objectStore.add(item) request.onsuccess = function(event) { console.log('插入成功!', index) console.log(event.target.result, item.id); // add()方法調用成功後result是被添加的值的鍵(id) } })
修改數據庫中的數據
var objectStore = transaction.objectStore('person') objectStore.put({"name": "李四", "age": "22", "sex": "男", "id": "12" })
該方法與add()不一樣之處在於,數據庫中若存在相同主鍵或者惟一性索引重複,則會更新該條數據,不然插入新數據。
從數據庫中刪除數據
var objectStore = transaction.objectStore('person') var request = objectStore.delete('12'); // 經過鍵id來刪除 request.onsuccess = function(event) { console.log('刪除成功!'); }
從數據中獲取數據
var objectStore = transaction.objectStore('person') var request = objectStore.get('13') request.onsuccess = function(event) { console.log('獲取成功!', event) }
使用索引
在前面,咱們建立了兩個索引name和age, 配置對象裏面的unique屬性標誌該值是否惟一
如今咱們想找到name屬性值爲'張三'的對象,就可使用索引。
var objectStore = db.transaction('person').objectStore('person') // 打開對象存儲空間 var index = objectStore.index('name') // 使用索引 var request = index.get('張三') // 建立一個查找數據的請求 request.onsuccess = function(event) { console.log('The result is:', event.target.result) }
使用遊標
使用一次索引,咱們只能獲得一條數據; 若是咱們須要獲得全部數據,或某一類數據,可使用遊標.
獲得一個能夠操做遊標的請求對象有兩個方法:
// 匹配值爲Bill的數據 var lowerBoundKeyRange = IDBKeyRange.only("Bill") // 匹配全部在 "Bill" 前面的, 包括 "Bill" var lowerBoundKeyRange = IDBKeyRange.lowerBound("Bill"); // 匹配全部在 「Bill」 前面的, 可是不須要包括 "Bill" var lowerBoundOpenKeyRange = IDBKeyRange.lowerBound("Bill", true); // 匹配全部在'Donna'後面的, 可是不包括"Donna" var upperBoundOpenKeyRange = IDBKeyRange.upperBound("Donna", true); // 匹配全部在"Bill" 和 "Donna" 之間的, 可是不包括 "Donna" var boundKeyRange = IDBKeyRange.bound("Bill", "Donna", false, true);
遊標默認遍歷方向是按主鍵從小到大,有時候咱們倒序遍歷,此時能夠給openCursor()
方法傳遞第二個參數: direction: next|nextunique|prev|prevunique
遊標的使用有如下幾處:
var list = []; var index = db.transaction('person').objectStore('person') index.openCursor().onsuccess = function(event) { var cursor = event.target.result if (cursor) { console.log('cursor.value:', cursor.value); list.push(cursor.value) cursor.continue() } else { console.log('list:', list) } }
var list = [] var index = db.transaction('person').objectStore('person').index('age') index.openCursor('24').onsuccess = function(event) { var cursor = event.target.result if (cursor) { console.log('cursor.value:', cursor.value); list.push(cursor.value) cursor.continue() } else { console.log('list:', list) } }
使用遊標時,須要在成功回調裏拿到result對象,判斷是否取完了數據:若數據已取完,result是undefined; 若未取完,則result是個IDBCursorWithValue對象,需調用continue()方法繼續取數據。 也能夠根據本身需求, 對數據進行過濾。
在索引age上使用openCursor()方法時,若不傳參數,則會遍歷全部數據
關閉和刪除數據庫
關閉數據庫只須要在數據庫對象db上調用close()方法便可 db.close()
關閉數據庫後,db對象仍然保存着該數據庫的相關信息,只是沒法再開啓事務
刪除數據庫則須要使用indexedDB.deleteDatabase(dbName)
方法