Safari開啓無痕模式後,localStorage和sessionStorage爲空,對其進行set操做也會報錯,也就是說這種狀況下,storage是被禁止使用了。接下來講一下解決方法。瀏覽器
解決方案服務器
咱們項目框架上的解決方法是對storage進行一層封裝,遇到這種開啓無痕模式的狀況,會定義一個window的全局變量,把以前準備存放到storage的內容改成存到這個全局變量中。cookie
注意,無痕模式下localStorage和sessionStorage對象自己依然是存在的,只是調用setItem方法是會報錯。下面是無痕模式下報錯的截圖:session
因此正確的判斷代碼應該是這樣:框架
try {
sessionStorage.setItem('private_test', 1);
} catch (e) {
//無痕模式
}
複製代碼
咱們會另外定義一個NameStorage對象,在原生storage失效時使用:this
// 隱私模式下面,把臨時值存到window.name中去
function NameStorage(type) {
this.store = NameStorage[type];
}
Object.assign(NameStorage.prototype, {
getItem: function(key) {
return this.store[key];
},
setItem: function(key, value) {
this.store[key] = value;
this._saveNameValue();
},
removeItem: function(key) {
delete this.store[key];
this._saveNameValue();
},
clear: function() {
this.store = {};
this._saveNameValue();
},
_saveNameValue: function() {
var ret = {
session: NameStorage.session,
local: NameStorage.local
}
window.name = JSON.stringify(ret);
}
});
複製代碼
上面會把全部的local和session數據存儲到window.name上去,而後在每一個頁面啓動時,調用一下keepName方法,把window.name的數據拿下來放到NameStorage上面。這時候,只須要調用new NameStorage('local')來代替localStorage進行操做就好了spa
function keepName () {
if (keepName.done) {
return;
}
var ret;
if (window.name) {
try {
ret = JSON.parse(window.name);
} catch (e) {
ret = {};
}
}
if (!_.isPlainObject(ret)) {
ret = {};
}
if (!ret.session) {
ret.session = {};
}
if (!ret.local) {
ret.local = {};
}
NameStorage.session = ret.session;
NameStorage.local = ret.local;
keepName.done = true;
}
複製代碼
● 無痕模式下,localStorage和sessionStorage的報錯信息是:QuotaExceededError,code爲22,這個實際上是storage存儲空間用完了報的錯,就好比當前瀏覽器storage內存爲5mb,你已經存儲了5mb的數據後,再進行setItem操做就會報這個錯誤。prototype
● 因此我猜測無痕模式下,瀏覽器是把storage的內存先清空,而後再設置最大值爲0,這樣調用setItem就直接報錯了。code
● 另外無痕模式下cookie是可使用的,大概由於cookie是跟服務器有關,而storage是屬於瀏覽器的特性吧。對象
● 最後還有一種狀況,就是無痕模式下打開了某個頁面,而後把瀏覽器關閉再打開,這個時候會打開訪問的頁面,可是window.name已經丟失了,因此就拿不到之前存儲的數據了。這種狀況只能頁面作容錯處理了。