前端數據本地存儲介紹


本文介紹本地數據存儲的選型。簡單總結一些查詢到的關於本地數據存儲的技術。

控制台展示前端存儲

Chrome:
 
image.png
前端離線存儲目前支持 Cookie、localStorage、sessionStorage、IndexedDB、Web SQL Database以及FileSystem.

本地存儲概覽

1)本地數據存儲:一般存儲的都是數據

  • Cookie:瀏覽器均支持,容量為4KB,用起來超級麻煩,而且限制極大;不適合
  • IE用戶數據(UserData):僅IE支持
  • Web存儲機制(Web Storage):H5,容量為5M。可以做key value 的存儲
    - localStorage
    - sessionStorage :其實算不上離線存儲,因為網頁關閉了,存儲就會丟棄。
    - globalStorage(Firefox獨有,Firefox13起就不再支持)
  • 數據庫存儲:
    - IndexDB:前端的nosql數據庫。
    - Web SQL:關系數據庫,需要注意的是,HTML5會放棄Web SQL

2)離線存儲(應用緩存):一般存儲的是網頁

  • Cache Storage:定義在 Service Worker 的規范中,配合 Service Worker 進行離線緩存
  • Application Cache:在定稿的 HTML 5.1 中被拿到了

存儲方式的詳解和比較

1. 小容量的 cookie

1.1 說明

HTTP Cookie,最初用於在客戶端存儲會話信息。該標准要求服務器對任意 HTTP 請求發送 Set-Cookie HTTP 頭作為響應的一部分,其中包含會話信息。瀏覽器會存儲這樣的會話信息,並在這之后,通過為每個請求添加 Cookie HTTP 頭將信息發送回服務器。

【舉例如下】:
 
storage-cookie-header.png
1.2 使用

在 JavaScript 中可以通過 document.cookie 設置字段和進行訪問。

// 設置 cookie 字段 document.cookie = 'name=Lucy'; // 更好的設置方式: document.cookie = encodeURIComponent('age') + '=' + encodeURIComponent(25); // 訪問 cookie document.cookie // 刪除 cookie(設置存儲有效時長為過去時間) var date = new Date(); date.setDate(date.getDate() + '設置時長'); document.cookie = 'name=Lucy;expires=' + date.toUTCString(); 
 
storage-cookie-js-use.png
1.3 訪問限制及存儲時長

cookie 可以設置訪問域,在設置 cookie 的時候,設定了 cookie 的訪問域名為一個頂級域名,則可以達到幾個子域名共享 cookie 的效果,如騰訊網 www.qq.com 與微信網頁版 wx.qq.com 共享了 pac_uid,以及不同頁面的購物車共享。
如果設定了 cookie 的超時時間,則 cookie 將在到期的時候失效。
如果沒有設定超時時間,則是 session 級別的(注意上圖 Expires/Max-Age 一欄),在退出瀏覽器時,該 cookie 將消失。
cookie 的 session 不同於 sessionStorage 的 session,cookie 的 session 是指在未關閉瀏覽器的情況下,所有的 tab 級別的頁面或新開,或刷新,均屬於一個 session。

1.4 cookie 的優缺點

優點:

可控制過期時間,使其不會長期有效
可擴展、可用性比較好,可跨域共享
可加密減少cookie被破解的可能性
兼容性好
缺點:

數量和長度有限制
在請求頭上帶着數據安全性差


 
webstorage.png
1.5 應用場景

一般非到不得已,不要在 cookie 里面存東西,更不要存儲重要和敏感的數據。如果要存儲的話,建議存儲一些同步訪問頁面的時候必須要被帶到服務端的信息。

客戶端登錄,用於保存用戶信息。如“下次自動登錄”的選項,勾選之后下次就不需要重復驗證。通過 cookie 可以保存用戶的 id。
創建購物車。可以實現不同頁面之間的數據同步(同一個域名下是可以共享cookie的),同時在提交訂單的時候又會把這些cookie傳到后台。
跟蹤用戶行為。例如百度聯盟會通過cookie記錄用戶的偏好信息,從而推薦個性化推廣信息,如頁面上的小廣告。這是可以禁用的,也是cookie的缺點之一。

2. Web Storage:僅存儲於客戶端

定義了兩種用於存儲數據的對象:sessionStorage 和 localStorage,后兩者是Storage的實例。

注意:Storage 類型只能存儲字符串。非字符串的數據在存儲之前會被轉換成字符串。

 
webstorage.png
2.1 目的及兩個主要目標
  • 克服由 cookie 帶來的一些限制,當數據需要被嚴格控制在客戶端上時,無須持續地將數據發回服務器。
  • (目標)提供一種在 cookie 之外存儲會話數據的途徑;
  • (目標)提供一種存儲大量可以跨會話存在的數據的機制。
2.2 訪問方式

這兩個對象在瀏覽器中都是以 windows 對象屬性的形式存在,在 JavaScript 中可以直接通過 sessionStorage 和 localStorage 訪問。

2.3 Storage 的實例方法
  • clear:刪除所有值,Firefox中沒有實現
  • getItem(name):根據指定的名字 name 獲取對應的值
  • key(index):獲得 index 處的值的名字
  • removeItem(name):刪除由 name 指定的名值對兒
  • setItem(name, value):為指定的 name 設置一個對應的值
2.4 sessionStorage 和 localStorage 介紹

短暫的 sessionStorage

1) 使用:
 
storage-sessionStorage.png
2) 訪問限制:

同源策略:不同於cookie,sessionStorage訪問限制更高,只有當前設定sessionStorage的域下才能訪問;
單標簽頁:兩個tab(相同域)之間不能互通;
在新開的tab下或者關閉本tab之后再打開,也不能訪問之前寫下的sessionStorage;
刷新本tab可以訪問。

3) 特點及應用場景:

主要用於僅針對會話的小段數據的存儲。
建議存儲一些當前頁面刷新需要存儲,且不需要在tab關閉時候留下的信息。
可以用來檢測用戶是否是刷新進入的頁面,如音樂播放器恢復播放進度條的功能。
非常適合單頁應用程序,可以方便在各業務模塊進行傳值。
持久的 localStorage(隱身窗口例外)

  1. 使用: 同 sessionStorage

  2. 訪問限制:

同源策略:同 sessionStorage,要訪問同一個 localStorage,頁面必須來自同一個域名(子域名無效),使用同一種協議,在同一個端口上;
localStorage 設定后,刷新或新開 tab 是可以訪問到的,關閉瀏覽器重新打開原先tab也可訪問。

  1. 特點及應用場景:

持久保存客戶端數據,數據保留到通過JavaScript刪除或者用戶清除瀏覽器緩存。
如果有一些數據,服務器難以承載其壓力,但又要與用戶的信息綁定,可以使用 localStorage 存儲一些狀態,這樣既能緩解服務器壓力,也可以存儲用戶的數據。
數據比較大的臨時保存方案。如在線編輯文章時的自動保存。
多頁面訪問共同數據。sessionStorage只適用於同一個標簽頁,localStorage相比而言可以在多個標簽頁中共享數據。

localStorage 與 sessionStorage 的區別總結

H5的兩種存儲技術的最大區別就是生命周期
localStorage是本地存儲,存儲期限不限;
sessionStorage是會話存儲,頁面關閉數據就會丟失。
sessionStorage 有單標簽頁限制,localStorage 則沒有。

2.5 Storage 存儲類型說明

Storage 類型只能存儲字符串。如果存儲的是對象,可以將對象序列化為字符串再存入。(以下以 localStorage 進行說明,sessionStorage 同樣適用)

2.6 Storage 大小限制及檢測

Web Storage 的限制因瀏覽器而異。一般來說,對存儲空間大小的限制都是以每個來源(協議、域和端口)為單位的,即每個來源都有固定大小的空間用於保存自己的數據。對於 localStorage 而言,大多數桌面瀏覽器會設置每個來源 5MB 的限制。對 sessionStorage 的限制也是因瀏覽器而異。

對於 Storage 的大小檢測,可以將 localStorage 和 sessionStorage 序列化,然后查看其字節數:

2.7 storage 事件

對 Storage 對象進行任何操作,都會在文檔上觸發 storage 事件,該事件的 event 對象有以下屬性:

domain:發生變化的存儲空間的域名
key:設置或者刪除的鍵名
newValue:如果是設置值,則是新值;如果是刪除鍵,則是null
oldValue:鍵被更改之前的值
使用時需要檢測 WebKit 是否支持 storage 事件。

2.8 Web Storage 和 Cookie 的區別總結

Web Storage 是為了更大容量存儲設計的,而Cookie的大小是受限的。

cookie 在每次請求一個新的頁面的時候都會被發送過去,在瀏覽器和服務器間來回傳遞,這樣無形中浪費了帶寬。

cookie 可以設定訪問域,在同源窗口中可以共享,而 web storage 受同源策略限制。

但是Cookie也是不可以或缺的:Cookie的作用是與服務器進行交互,作為HTTP規范的一部分而存在 ,而Web Storage僅僅是為了在本地“存儲”數據而生。

3. 數據庫:IndexDB 與 Web SQL

3.1 兩者的特點

websql 像關系型數據庫,使用 sql 語句進行操作。
indexdb 像 nosql,直接使用 js 方法操作數據。

訪問:indexdb 和 websql 與 web storage 一致,均是在創建數據庫的域名下才能訪問。且不能指定訪問域名。

存儲時間:這兩位的存儲時間也是永久,除非用戶清除數據,可以用作長效的存儲。

大小限制:理論上講,這兩種存儲的方式是沒有大小限制的。然而indexeddb的數據庫超過50M的時候瀏覽器會彈出確認。基本上也相當於沒有限制了。

性能測試:indexeddb查詢少量數據花費差不多20MS左右。大量數據的情況下,相對耗時會變長一些,但是也就在30MS左右,也是相當給力了,10W數據+,畢竟nosql。
而 websql 的效率也不錯,10w+數據,簡單查詢一下,只花費了20MS左右。

3.2 IndexDB 特點

它的數據不是保存在表中,而是保存在對象存儲空間中。
創建對象存儲空間時,需要定義一個鍵,然后就可以添加數據。
可以使用游標在對象存儲空間中查詢特定的對象。
而索引則是為了提高查詢速度而基於特定的屬性創建的。
說明:indexDB 目前兼容性還不是很好,Web SQL 雖然已經過時,但是其兼容性卻非常好,幾乎是移動端均可用(兼容性對比查看請移步:http://caniuse.com/#search=websql 以及 http://caniuse.com/#search=indexdb)。

因此,能用 indexdb,就用 indexdb,因為其代表了未來的發展方向,如果不能使用盡量使用 websql 進行代替。

3.3 IndexDB 異步 API

IndexDB 設計的操作完全是異步的。因此,大多數操作會以請求的方式進行,但這些操作會在后期執行,如果成功則返回結果,如果失敗則返回錯誤。差不多每一次 IndexDB 操作,都需要你注冊 onerror 或 onsuccess 事件處理程序,以確保適當地處理結果。


 
storage-IndexDB.png

打開數據庫時,實質上返回了一個DB對象,該對象存在於 result 中。

3.4 Web SQL Database

需要注意的是,HTML5已經會放棄Web SQL Database

放棄的原因如下:

This document was on the W3C Recommendation track but specification work has stopped. The specification reached an impasse: all interested implementors have used the same SQL backend (Sqlite), but we need multiple independent implementations to proceed along a standardisation path.
大概意思是:
該文件是W3C推薦標准,但規范的制定工作已經停止。該規范陷入僵局:所有感興趣的實現者都使用了相同的SQL后端(SQLite的),但我們需要多個獨立的實現沿着規范化的路徑進行。
翻譯參考:http://www.zhihu.com/question/41951041
有關標准參考: https://www.w3.org/TR/webdatabase/

如果你掌握過mysql,orancle,mssql等關系型數據庫,對於websql的理解還是比較容易的。

websql的關鍵技術點分為:

測試瀏覽器支持
創建數據庫
創建表格
插入數據等

用到的幾個核心方法:

openDatabase openDatabaseSycn 創建數據庫

transaction起事務
executeSql執行sql語句

詳情可以參考:http://blog.csdn.net/netcy/article/details/52188531

3.5 應用場景:

當我們是在做一個離線應用,或者webapp的時候,可以考慮使用本地數據庫中存取數據。如果不存大量的數據的話,其實localStorage就夠用了。亦或者,你想把一張用戶的皮膚圖片之類的大量數據存入客戶端緩存起來,localStorage已經不夠用了的話,也可以嘗試一下websql與indexeddb。

4.WebSQL

Web SQL是關系數據庫,通過SQL語句訪問
Web SQL 數據庫 API 並不是 HTML5 規范的一部分,但是它是一個獨立的規范,引入了一組使用 SQL 操作客戶端數據庫的 APIs。

支持情況:

Web SQL 數據庫可以在最新版的 Safari, Chrome 和 Opera 瀏覽器中工作。

核心方法:

①openDatabase:這個方法使用現有的數據庫或者新建的數據庫創建一個數據庫對象。

②transaction:這個方法讓我們能夠控制一個事務,以及基於這種情況執行提交或者回滾。

③executeSql:這個方法用於執行實際的 SQL 查詢。

打開數據庫:
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024,fn); //openDatabase() 方法對應的五個參數分別為:數據庫名稱、版本號、描述文本、數據庫大小、創建回調 
執行查詢操作:
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024); db.transaction(function (tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS WIN (id unique, name)'); }); 
插入數據:
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024); db.transaction(function (tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS WIN (id unique, name)'); tx.executeSql('INSERT INTO WIN (id, name) VALUES (1, "winty")'); tx.executeSql('INSERT INTO WIN (id, name) VALUES (2, "LuckyWinty")'); }); 
讀取數據:
db.transaction(function (tx) { tx.executeSql('SELECT * FROM WIN', [], function (tx, results) { var len = results.rows.length, i; msg = "<p>查詢記錄條數: " + len + "</p>"; document.querySelector('#status').innerHTML += msg; for (i = 0; i < len; i++){ alert(results.rows.item(i).name ); } }, null); }); 

由這些操作可以看出,基本上都是用SQL語句進行數據庫的相關操作,如果你會MySQL的話,這個應該比較容易用。

點我參考更多資料!

5.離線緩存(application cache)

本地緩存應用所需的文件

使用方法:

①配置manifest文件
頁面上:

<!DOCTYPE HTML> <html manifest="demo.appcache"> ... </html> 
Manifest 文件:

manifest 文件是簡單的文本文件,它告知瀏覽器被緩存的內容(以及不緩存的內容)。

manifest 文件可分為三個部分:

  • ①CACHE MANIFEST - 在此標題下列出的文件將在首次下載后進行緩存

  • ②NETWORK - 在此標題下列出的文件需要與服務器的連接,且不會被緩存

  • ③FALLBACK - 在此標題下列出的文件規定當頁面無法訪問時的回退頁面(比如 404 頁面)

完整demo:

CACHE MANIFEST # 2016-07-24 v1.0.0 /theme.css /main.js NETWORK: login.jsp FALLBACK: /html/ /offline.html 

服務器上:manifest文件需要配置正確的MIME-type,即 "text/cache-manifest"。

如Tomcat:

<mime-mapping> <extension>manifest</extension> <mime-type>text/cache-manifest</mime-type> </mime-mapping> 
常用API:

核心是applicationCache對象,有個status屬性,表示應用緩存的當前狀態:

0(UNCACHED) : 無緩存, 即沒有與頁面相關的應用緩存

1(IDLE) : 閑置,即應用緩存未得到更新

2 (CHECKING) : 檢查中,即正在下載描述文件並檢查更新

3 (DOWNLOADING) : 下載中,即應用緩存正在下載描述文件中指定的資源

4 (UPDATEREADY) : 更新完成,所有資源都已下載完畢

5 (IDLE) : 廢棄,即應用緩存的描述文件已經不存在了,因此頁面無法再訪問應用緩存

相關的事件:

表示應用緩存狀態的改變:

checking : 在瀏覽器為應用緩存查找更新時觸發

error : 在檢查更新或下載資源期間發送錯誤時觸發

noupdate : 在檢查描述文件發現文件無變化時觸發

downloading : 在開始下載應用緩存資源時觸發

progress:在文件下載應用緩存的過程中持續不斷地下載地觸發

updateready : 在頁面新的應用緩存下載完畢觸發

cached : 在應用緩存完整可用時觸發

Application Cache的三個優勢:

① 離線瀏覽

② 提升頁面載入速度

③ 降低服務器壓力

注意事項:
  1. 瀏覽器對緩存數據的容量限制可能不太一樣(某些瀏覽器設置的限制是每個站點 5MB)
  2. 如果manifest文件,或者內部列舉的某一個文件不能正常下載,整個更新過程將視為失敗,瀏覽器繼續全部使用老的緩存
  3. 引用manifest的html必須與manifest文件同源,在同一個域下
  4. 瀏覽器會自動緩存引用manifest文件的HTML文件,這就導致如果改了HTML內容,也需要更新版本才能做到更新。
  5. manifest文件中CACHE則與NETWORK,FALLBACK的位置順序沒有關系,如果是隱式聲明需要在最前面
  6. FALLBACK中的資源必須和manifest文件同源
  7. 更新完版本后,必須刷新一次才會啟動新版本(會出現重刷一次頁面的情況),需要添加監聽版本事件。
  8. 站點中的其他頁面即使沒有設置manifest屬性,請求的資源如果在緩存中也從緩存中訪問
  9. 當manifest文件發生改變時,資源請求本身也會觸發更新

點我參考更多資料!

離線緩存與傳統瀏覽器緩存區別:
  1. 離線緩存是針對整個應用,瀏覽器緩存是單個文件

  2. 離線緩存斷網了還是可以打開頁面,瀏覽器緩存不行

  3. 離線緩存可以主動通知瀏覽器更新資源



作者:謝大見
鏈接:https://www.jianshu.com/p/43a64fb84337
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM