聊一聊常見的瀏覽器端數據存儲方案

前言:

五一假期在擼代碼的時候用到cookie,感受對瀏覽器的數據存儲方案不是很瞭解,所以又去翻了兩本大頭書中間的關於瀏覽器端數據存儲的章節,同時去MDN逛了逛,又看了幾篇文章,算是對瀏覽器的數據存儲方案有了一個瞭解,在此總結一下!web

瀏覽器存儲

在瀏覽器端存儲數據對咱們是頗有用,這至關於賦予瀏覽器記憶的功能,能夠紀錄用戶的全部狀態信息,加強用戶體驗。好比當紀錄用戶的登錄狀態時,可讓用戶可以更快的進行訪問,而不是每次登錄時都須要去進行繁瑣的操做。chrome

總的來講,如今市面上最多見的數據存儲方案是如下三種:數據庫

  • Cookie
  • web存儲 (locaStorage和seesionStorage)
  • IndexedDB

圖片.png

Cookie

Cookie的又稱是HTTP Cookie,最初是在客戶端用於存儲會話信息,從底層來看,它做爲HTTP協議的一種擴展實現,Cookie數據會自動在web瀏覽器和web服務器之間傳輸,所以在服務器端腳本就能夠讀寫存儲的cookie的值,所以Cookie一般用於存儲一些通用的數據,好比用戶的登錄狀態,首選項等。雖然隨着時代的進步,HTML5所提供的web存儲機制已經逐步替代了Cookie,但有些較爲老的瀏覽器仍是不兼容web存儲機制,所以正處於這個老舊更替階段的咱們對於它仍是要了解了解的。(好比我這個瓜皮還在用它,2333)windows

Cookie的優勢

首先因爲操做Cookie的API很早就已經定義和實現了,所以相比於其餘的數據存儲方式,Cookie的兼容性很是的好,兼容如今市面上全部的主流瀏覽器,咱們在使用它的時候徹底不用擔憂兼容問題。瀏覽器

Cookie的缺點

說到Cookie的缺點,那就有點多了,否則也不會在Cookie後面出現web存儲等新的數據存儲的方案了。 總結起來Cookie的缺點主要是如下幾點:安全

  1. 存儲量小。雖不一樣瀏覽器的存儲量不一樣,但基本上都是在4kb左右。
  2. 影響性能。因爲Cookie會由瀏覽器做爲請求頭髮送,所以當Cookie存儲信息過多時,會影響特定域的資源獲取的效率,增長文檔傳輸的負載。
  3. 只能儲存字符串。
  4. 安全問題。存儲在Cookie的任何數據能夠被他人訪問,所以不能在Cookie中儲存重要的信息。
  5. 因爲第三方Cookie的濫用,因此不少老司機在瀏覽網頁時會禁用Cookie,因此咱們不得不測試用戶是否支持Cookie,這也是很麻煩的一件事。

Cookie的操做

基本的Cookie操做主要有三個:讀取,寫入和刪除。但在JavaScript中去處理cookie是一件很繁瑣的事情,由於cookie中的全部的名字和值都是通過URI編碼的,因此當咱們必須使用decodeURICompoent來進行解碼才能獲得cookie的值。咱們來看看CookieUtil對象是如何操縱cookie的:bash

var CookieUtil = {
	// get可根據cookie的名字獲取相應的值
	get: function() {
		const cookieName = encodeURIcOMPONET(name) + "=",
			   cookieStart = document.cookie.indexOf(cookieName),
			   cookieValue = null
		if(cookieStart > -1) {
			const cookieEnd = document.cookie.indexOf(";", cookieStart)
			if(cookieEnd == -1) {
				cookieEnd = document.cookie.length
			}
			cookieValue = decodeURICompoent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd))	
		}
		return cookieValue
	}
	// set設置一個cookie
	set: function(name, value, expires, path, domain, secure) {
		var cookieText = encodeURIComponet(name)+"="+encodeURIComponet(value)
		if(expires instanceof Date) {
			cookieText += "; expires=" + expires.toGMTString()
		}
		if(path) {
			cookieText += ";path=" + path
		}
		if(domain) {
			cookieText += "; domain" + domain
		}
		if(secure) {
			cookieText += "; secure"
		}
		document.cookie = cookieText
	}
	// 刪除已有的cookie
	unset: function(name, path, domain, secure) {
		this.set(name, "", new Date(0), path, domain, secure)
	}
}
複製代碼

是否是很麻煩,不管是獲取一個cookie的值或是設置一個cookie都是很麻煩的事情,這也成爲了後續的瀏覽器數據存儲方案出現的一大緣由。服務器

web存儲

web存儲機制最初做爲HTML5的一部分被定義成API的形式,但又因爲其自己的獨特性與其餘的一些緣由而剝離了出來,成爲獨立的一個標準。web存儲標準的API包括locaStorage對象和seesionStorage對象。它所產生的主要緣由主要出於如下兩個緣由:cookie

  • 人們但願有一種在cookie以外存儲回話數據的途徑。
  • 人們但願有一種存儲大量能夠跨會話存在的數據的機制。

(注:其實在最初的web存儲規範中包含了兩種對象的定義:seesionStorage和globalStorage,這兩個對象在支持這兩個對象的瀏覽器中都是以windows對象屬性的形式存在的)網絡

locaStorage

locaStorage對象在修訂過的HTML5規範中做爲持久保存客戶端數據的方案取代了咱們上面所提到的globalStorage。從功能上來說,咱們能夠經過locaStorage在瀏覽器端存儲鍵值對數據,它相比於cookie而言,提供了更爲直觀的API,且在安全上相對好一點 ,並且雖然locaStorage只能存儲字符串,但它也能夠存儲字符串化的JSON數據,所以相比於cookie,locaStorage能存儲更復雜的數據。總的來講相較於cookie,locaStorage有如下優點:

  • 提供了簡單明瞭的API來進行操做
  • 更加安全
  • 可儲存的數據量更大

也正是出於以上這些緣由,locaStorage被視爲替代cookie的解決方案,但仍是要注意不要在locaStorage中存儲敏感信息。

locaStorage的基本語法

locaStorage的基本操做很簡單,示例以下:

// 使用方法存儲數據
locaStorage.setItem("name", "Srtian")
// 使用屬性存儲數據
locaStorage.say = "Hello world"
// 使用方法讀取數據
const name = locaStorage.getItem("name")
// 使用屬性讀取數據
const say = locaStorage.say
// 刪除數據
locaStorage.removeItem("name")
複製代碼

但須要注意的是,咱們上面的示例全是存儲字符串格式的數據,當咱們須要傳輸其餘格式的數據時,咱們就須要將這些數據所有轉換爲字符串格式,而後再進行存儲:

const user = {name:"Srtian", age: 22}
localStorage.setItem("user", JSON.stringify(user))
複製代碼

固然,咱們在獲取值的時候也別忘了將其轉化回來:

var age = JSON.parse(locaStorage.user)
複製代碼

locaStorage儲存數據的有效期與做用域

經過locaStorage存儲的數據時永久性的,除非咱們使用removeItem來刪除或者用戶經過設置瀏覽器配置來刪除,負責數據會一直保留在用戶的電腦上,永不過時。

locaStorage的做用域限定在文檔源級別的(意思就是同源的才能共享),同源的文檔間會共享locaStorage的數據,他們能夠互相讀取對方的數據,甚至有時會覆蓋對方的數據。固然,locaStorage的做用域一樣也受瀏覽器的限制。

locaStorage的兼容

locaStorage的兼容以下表所示:

Feature 	Chrome 	Edge 	Firefox (Gecko) Internet Explorer 	Opera 	Safari (WebKit)
localStorage 	4 	(Yes) 	   3.5 	            8 	             10.50     4
sessionStorage 	5 	(Yes) 	   2 	            8 	             10.50 	   4
複製代碼

sessionStorage

sessionStorage是web存儲機制的另外一大對象,sessionStorage 屬性容許咱們去訪問一個 session Storage 對象。它與 localStorage 類似,不一樣之處在於 localStorage裏面存儲的數據沒有過時時間設置,而Session Storage只存儲當前會話頁的數據,且只有當用戶關閉當前會話頁或瀏覽器時,數據纔會被清除。

sessionStorage的基本語法

咱們能夠經過下面的語法,來保存,獲取,刪除數據,大致語法與:

// 保存數據到sessionStorage
sessionStorage.setItem('name', 'Srtian');

// 從sessionStorage獲取數據
var data = sessionStorage.getItem('name');

// 從sessionStorage刪除保存的數據
sessionStorage.removeItem('name');

// 從sessionStorage刪除全部保存的數據
sessionStorage.clear();
複製代碼

下面的示例會自動保存一個文本輸入框的內容,若是瀏覽器因偶然因素被刷新了,文本輸入框裏面的內容會被恢復,寫入的內容不會丟失:

// 獲取文本輸入框
var field = document.getElementById("field")

// 檢測是否存在 autosave 鍵值
// (這個會在頁面偶然被刷新的狀況下存在)
if (sessionStorage.getItem("autosave")) {
  // 恢復文本輸入框的內容
  field.value = sessionStorage.getItem("autosave")
}
// 監聽文本輸入框的 change 事件
field.addEventListener("change", function() {
  // 保存結果到 sessionStorage 對象中
  sessionStorage.setItem("autosave", field.value)
})
複製代碼

在兼容性和優勢方面,sessionStorage和locaStorage是差很少的,所以在此也就很少說了,下面咱們來聊一聊IndexedDB。

IndexedDB

雖然web存儲機制對於存儲較少許的數據很是便捷好用,但對於存儲更大量的結構化數據來講,這種方法就不太知足開發者們的需求了。IndexedDB就是爲了應對這個需求而產生的,它是由HTML5所提供的一種本地存儲,用於在瀏覽器中儲存較大數據結構的 Web API,並提供索引功能以實現高性能查找。它通常用於保存大量用戶數據並要求數據之間有搜索須要的場景,當網絡斷開時,用戶就能夠作一些離線的操做。它較之SQL更爲方便,不須要寫一些特定的語法對數據進行操做,數據格式是JSON。

IndexedDB的基本語法

使用IndexedDB在瀏覽器端存儲數據會比上述的其餘方法更爲複雜。首先,咱們須要建立數據庫,並指定這個數據庫的版本號:

// 注意數據庫的版本號只能是整數
const request = IndexedDB.open(databasename, version)
複製代碼

而後咱們須要生成處理函數,須要注意的是onupgradeneeded 是咱們惟一能夠修改數據庫結構的地方。在這裏面,咱們能夠建立和刪除對象存儲空間以及構建和刪除索引。 :

request.onerror = function() {
	// 建立數據庫失敗時的回調函數
}
request.onsuccess = function() {
	// 建立數據庫成功時的回調函數
}
request.onupgradeneededd = function(e) {
	 // 當數據庫改變時的回調函數
}

複製代碼

而後咱們就能夠創建對象存儲空間了,對象存儲空間僅調用createObjectStore()就能夠建立。這個方法使用存儲空間的名稱,和一個對象參數。即使這個參數對象是可選的,它仍是很是重要的,由於它可讓咱們定義重要的可選屬性和完善你但願建立的對象存儲空間的類型。

request.onupgradeneeded = function(event) {
	const db = event.target.result
	const objectStore = db.createObjectStore('name', { keyPath:'id' })
}
複製代碼

對象的存儲空間咱們已經創建好了,接下來咱們就能夠進行一系列的騷操做了,好比來個蛇皮走位!不不不,口誤口誤,好比添加數據:

addData: function(db, storename, data) {
	const store = store = db.transaction(storename, 'readwrite').objectStore(storename)
	for(let i = 0; i < data.length; i++) {
		const request = store.add(data[i])
		request.onerror = function() {
			console.error('添加數據失敗')
		}
		request.onsuccess = function() {
			console.log('添加數據成功')
		}
	}
}
複製代碼

若是咱們想要修改數據,語法與添加數據差很少,由於重複添加已存在的數據會更新本來的數據,但仍是有細小的差異:

putData: function(db, storename, data) {
	const store = store = db.transaction(storename, 'readwrite').objectStore(storename)
	for(let i = 0; i < data.length; i++) {
		const request = store.put(data[i])
		request.onerror = function() {
			console.error('修改數據失敗')
		}
		request.onsuccess = function() {
			console.log('修改數據成功')
		}
	}
}
複製代碼

獲取數據:

getDataByKey: function(db, storename, key) {
	const store = store = db.transaction(storename, 'readwrite').objectStore(storename)
	const request = store.get(key)
	request.onerror = function() {
		console.error('獲取數據失敗')
	}
	request.onsuccess = function(e) {
		const result = e.target.result
		console.log(result)
	}
}
複製代碼

刪除數據:

deleteDate: function(db, storename, key) {
	const store = store = db.transaction(storename, 'readwrite').objectStore(storename)
	store.delete(key)
	console.log('已刪除存儲空間' + storename + '中的' + key + '紀錄')
}
複製代碼

關閉數據庫:

db.close
複製代碼

IndexedDB的優勢(相較於前面的存儲方案)

  • 擁有更大的儲存空間
  • 可以處理更爲複雜和結構化的數據
  • 擁有更多的交互控制
  • 每一個'database'中能夠擁有多個'database'和'table'

IndexedDB的侷限性

瞭解了IndexedDB的優勢,咱們固然也要來聊一聊IndexedDB的侷限性與適用的場景:

1. 存儲空間限制

一個單獨的數據庫項目的大小沒有限制。然而可能會限制每一個 IndexedDB 數據庫的大小。這個限制(以及用戶界面對它進行斷言的方式)在各個瀏覽器上也可能有所不一樣:

  • Firefox: 對 IndexedDB 數據庫的大小沒有限制。在用戶界面上只會針對存儲超過 50 MB 大小的 BLOB(二進制大對象)請求權限。這個大小的限額能夠經過 dom.indexedDB.warningQuota 首選項進行自定義。(定義在 http://mxr.mozilla.org/mozilla-central/source/modules/libpref/src/init/all.js)。
  • Google Chrome:https://developers.google.com/chrome...rage#temporary

2. 兼容性問題

圖片.png
從上面的圖咱們能夠看出對於IndexedDB的兼容來說比前面所說起的存儲方案要差很多,所以在使用IndexedDB時,咱們也要好好的考慮兼容性的問題

3. indexedDB受同源策略的限制

indexedDB使用同源原則,這意味着它把存儲空間綁定到了建立它的站點的源(典型狀況下,就是站點的域或是子域),因此它不能被任何其餘源訪問。要着重指出的一點是 IndexedDB 不適用於從另外一個站點加載進框架的內容 (無論是 仍是 。這是一項安全措施。詳情請看這個:https://bugzilla.mozilla.org/show_bug.cgi?id=595307

除此以外,IndexedDB還存在諸如:不適合存儲敏感數據,相較於web存儲機制的操做更加複雜等問題,這都是咱們在使用IndexedDB時須要考慮的。

相關文章
相關標籤/搜索