1. 原因
js代碼是運作在記憶體中的,代碼運作時的所有變量、函數也都是儲存在記憶體中的。
重新整理頁面,以前申請的記憶體被釋放,重新加載腳本代碼,變量重新指派,是以這些資料要想存儲就必須存儲在外部,例如:Local Storage、Session Storage、Index DB等。這些都是浏覽器提供的API,讓你可以将資料存儲在硬碟上,做持久化存儲。具體選擇哪一個就根據你實際需求來選擇。
二、解決方案
在用戶端存儲資料:
HTML5提供了2種在用戶端存儲資料的新方法:localStorage沒有時間期限,除非将它移除,sessionStorage即會話,當浏覽器關閉時會話結束,有時間期限,具有自行百度。
之前,這些都是由cookie完成的,但是cookie不适合大量資料的存儲,因為它們由每個對伺服器的請求來傳遞,這使得cookie速度很慢,而且效率不高。
web存儲分為localStorage個sessionStorage。
差別在于存儲的有效期和作用域不同。
通過localStorage存儲的資料是永久性的,除非web應用刻意删除存儲的資料,或者使用者通過設定浏覽器配置(浏覽器提供的特定的UI)來删除,否則資料将一直儲存在使用者的電腦上,永不過期。
localStorage的作用域是限定在文檔源級别的。同源的文檔間共享同樣的localStorage資料(不論該源的腳本是否真正的通路localStorage)。他們可以互相讀取對方的資料,甚至可以覆寫對方的資料。但是,非同源的文檔間互相都不能讀取或者覆寫對方的資料。(即使他們運作的腳本是來自同一台第三方的伺服器也不行)。
sessionStorage存儲資料的有效期和存儲資料的腳本所在的最頂層的視窗或者是浏覽器标簽頁是一樣的,一旦視窗或者标簽頁被永久關閉了,那麼所有通過sessionStorage存儲的資料也都被删除了。
我這裡使用sessionStorage,這裡需要注意的是vuex中的變量是響應式的,而sessionStorage不是,當你改變vuex中的狀态,元件會檢測到改變,而sessionStorage就不會了,頁面要重新重新整理才可以看到改變,是以應讓vuex中的狀态從sessionStorage中得到,這樣元件就可以響應式的變化
三、具體實作
應用背景是使用者登入後儲存狀态,退出後移除狀态
//mutations
ADD_LOGIN_USER (state,data) { //登入,儲存狀态
sessionStorage.setItem("username", data); //添加到sessionStorage
sessionStorage.setItem("isLogin",true);
state.username=data, //同步的改變store中的狀态
state.isLogin=true
},
SIGN_OUT (state) { //退出,删除狀态
sessionStorage.removeItem("username"); //移除sessionStorage
sessionStorage.removeItem("isLogin");
state.username='' //同步的改變story中的狀态
state.isLogin=false
}
//getters
isLogin (state) {
if (!state.isLogin) {
state.isLogin=sessionStorage.getItem('isLogin'); //從sessionStorage中讀取狀态
state.username=sessionStorage.getItem('username');
}
return state.isLogin
}
總體的實作思路是讓vuex中store的狀态從sessionStorage取值,并和sessionStorage保持一緻
getters:{
userInfo(state){
if(!state.userInfo){
state.userInfo = JSON.parse(sessionStorage.getItem('userInfo'))
}
return state.userInfo
}
},
mutations:{
LOGIN:(state,data) => {
state.userInfo = data;
sessionStorage.setItem('userInfo',JSON.stringify(data));
},
LOGOUT:(state) => {
state.userInfo = null;
sessionStorage.removeItem('userInfo');
}
},
ps:需要注意的是state裡的userInfo初始化一定要是null,而不是{},否則那個判斷就一直為true啦(個人遇到的一個小問題)