localStorage 還能這麼用

2021-08-09 17:51:50 字數 3382 閱讀 2467

html5中 web storage 的出現,主要是為了彌補使用 cookie 作為本地儲存的不足。cookie 儲存的資料量非常小,而且資料會自動攜帶到請求頭里,但伺服器端可能並不關心這些資料,所以會造成頻寬的浪費。

web storage 提供了兩個儲存物件:localstorage 和 sessionstorage。

sessionstorage 儲存的資料僅在本次會話有用,會話結束後會自動失效,而且資料僅在當前視窗有效,同一源下新視窗也訪問不到其他視窗基於

sessionstorage 儲存的資料。也是由於這些特性,導致 sessionstorage 的使用場景會比較少。

localstorage 可以永久儲存,而且同源下資料多視窗也能共享,。看起來很美好,但 localstorage 也有短板,絕大多數瀏覽器有 5m 的大小限制。但是這不足以成為大家使用 localstorage 的障礙,要知道 cookie 只有 4k 的大小,多了一千多倍,偷著樂吧。

講這個內容的文章網上太多了,現在再來講有點老套了。這裡就不做更多介紹了,不清楚的讀者可以看這裡。

有兩點需要注意一下。在setitem時,可能會達到大小限制,最好加上錯誤捕捉:

try

catch(e

)}

function

isquotaexceeded(e

)break;}

}elseif(

e.number

=== -

2147024882)}

return

quotaexceeded;}

另外在儲存容量快滿時,會造成getitem效能急劇下降 2。

我們下面看看 localstorage 有哪些腦洞大開的用法。

你不禁要問,http 協議不是本來就支援快取檔案嗎(之前寫過一篇文章《web快取之http指南》),為什麼還要使用 localstorage 來快取?為了可程式設計化,通俗一點說就是把命運握在自己手中。

http 協議的快取,可以由使用者瀏覽器清除或禁用快取,也可以由 web 伺服器設定過期時間或不快取。對於前端工程師,這更像是乙個黑盒,想要決定檔案是訪問快取還是訪問遠端顯得有些力不從心了。

使用 localstorage 控制檔案快取的方式有兩種:

使用 loader 載入靜態檔案

借助伺服器端將靜態檔案 inline 化

這兩種方式一般都會提前做好快取過期策略,通常是使用版本號來控制,下面還會細講。否則檔案新版上線,使用者客戶端還是舊版,這就麻煩大了,而且這類問題,還不好除錯不好重現。

由於請求都是動態發出的,所以可以對請求攔截處理。大致流程如下:

檢視請求的檔案 url 是否有快取到 localstorage

過期或不匹配,到第 2 大步

檔案內容有效,到第 4 大步

如果沒有,到第 2 大步

如果有,判斷檔案是否過期或版本號是否匹配

請求遠端檔案

快取最新檔案內容

執行檔案內容

這個方式有個開源庫:basket.js。

這個方式比上面那種更進一步,在第一次響應時把需要放入 localstorage 的檔案都內聯進 html 中,後面每次響應只要檔案版本沒有變化,都是渲染一段從 localstorage 載入該檔案的**。這樣做的好處是可以有效減少請求次數,即使是第一次。

版本號不匹配(版本號可記在 cookie 中,第一次訪問沒有版本號),服務端響應內容:

版本號匹配,服務端響應內容:

不過使用 localstorage 快取檔案會有 xss 的風險,而且造成的傷害可能是永久的。

你可能不禁又要問,不是有 postmessage 嗎?沒錯 postmessage 確實可以用於視窗或 iframe 間通訊,但是前提是你必須拿到開啟新窗或 iframe 的控制代碼物件:

var

popup

= window

.open

(...

popup 

details

...);

popup

.postmessage

("hello there!"

,"");

這樣在新窗中再開啟新窗,似乎就不好傳遞訊息了。

你可能還想問,為什麼要在視窗間通訊?好問題,沒有應用場景的技術都是耍流氓。像多視窗共用的一些元件,而且對資料實時同步都有較高要求的都會是這個技術的應用場景。比如通知中心上面的未讀數量,兩個視窗,a 視窗更新為 8,切到 b 視窗還是 9,這就造成了體驗不一致,這個例子可能還覺得無關痛癢;再比如購物車,兩個產品視窗,a 視窗新增到購物車,切到 b 視窗新增到購物車,發現沒有 a 新增的產品,這樣就比較嚴重了。這當然也可以通過每個視窗都與後台建立連線來更新,但使用者如果開十幾個視窗就開銷大了。

有了同源視窗通訊,我們就可以只有乙個視窗與後台建立連線,收到更新後,廣播給其他視窗就可以。說了這麼多,實現原理是怎樣的呢?

其實原理也簡單,每次 localstorage 中有任何變動都會觸發乙個 storage 事件,所有視窗都監聽這個事件,一旦有視窗更新 localstorage,其他視窗都會收到通知,根據事件中的 key 把不關心的變動過濾掉。原理是很簡單,但是要實現一套完整的廣播機制還是有些複雜,你需要:

不用擔心,已經有了不錯的開源實現:diy/intercom.js、tejacques/crosstab

你可能不滿足於用鍵值對儲存資料,你還想儲存更複雜的資料結構。

靈活訪問 json 格式的資料:typicode/lowdb

通過 sql 對資料 curd 操作:agershun/alasql

在填寫表單時,遇到瀏覽器奔潰或者誤操作導致填寫內容丟失,此刻使用者的內心也應該是奔潰的。誤操作還可以加乙個beforeunload事件,在關閉瀏覽器或跳出當前頁前提醒一下使用者。那瀏覽器崩潰呢,將資料變更實時儲存到後台,這樣似乎開銷很大,實時儲存到 localstorage 是個不錯的解決方案,真巧,也有乙個開源實現:simsalabim/sisyphus

檔案快取現在有更好的解決方案,沒錯,說的就是 service worker 的 cachestorage。

不過多了解一些腦洞大開的想法,有利於拓展解決問題的思路。

參考: 

1:always catch localstorage security and quota exceeded errors

2:measuring localstorage performance

3:使用 sri 增強 localstorage **安全

獲獎作品1元購,設計順德D DAY大賽還能這樣玩?

2019 年是電商直播元年,或許你還不了解薇婭 李佳琪等頭部直播帶貨明星,但是你肯定聽過那一句 omg,買它,買它!這幾乎成了直播帶貨的標準 話術 2020 年突如其來的新冠疫情,更是讓直播ekqtanda帶貨成為新的風口和社會風潮。疫情衝擊下,網路上湧現了一批批帶貨紅人,薇婭成功登陸 向上的力量 ...

本地快取localstorage

cookie,localstorage,sessionstorage都可以實現客戶端儲存,三者的區別有哪些了?cookie作為最早期的被設計web瀏覽器儲存少量資料,從底層看,它是作為http協議的一種擴充套件實現。cookie資料會自動在web瀏覽器和web伺服器之間傳輸資料。cookie有效期 ...

訪問資料localstorage

存 localstorage.setitem msg json.stringify this.resourcelists localstorage.setitem chosedresourceids json.stringify this.chosedids 取 var msg localstora...