狀態管理vuex
簡介
vuex 是專為 vue.js 應用程序開發的狀態管理模式。它采用集中存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。
vuex 也集成到 vue 的官方調試工具 devtools extension,提供了諸如零配置的 time-travel 調試、狀態快照導入導出等高級調試功能。
狀態管理核心
狀態管理有 5 個核心,分別是 state、getter、mutation、action 以及 module。分別簡單的介紹一下它們:
1、state
state 為單一狀態樹,在 state 中需要定義我們所需要管理的數組、對象、字符串等等,只有在這里定義了,在 vue.js 的組件中才能獲取你定義的這個對象的狀態。
2、getter
getter 有點類似 vue.js 的計算屬性,當我們需要從 store 的 state 中派生出一些狀態,那么我們就需要使用 getter,getter 會接收 state 作為第一個參數,
而且 getter 的返回值會根據它的依賴被緩存起來,只有 getter 中的依賴值(state 中的某個需要派生狀態的值)發生改變的時候才會被重新計算。
3、mutation
更改 store 中 state 狀態的唯一方法就是提交 mutation,就很類似事件。每個 mutation 都有一個字符串類型的事件類型和一個回調函數,我們需要改變 state 的值就要在回調函數中改變。我們要執行這個回調函數,那么我們需要執行一個相應的調用方法:store.commit。
4、action
action 可以提交 mutation,在 action 中可以執行 store.commit,而且 action 中可以有任何的異步操作。在頁面中如果我們要調用這個 action,則需要執行 store.dispatch
5、module
module 其實只是解決了當 state 中當代碼量很大很復雜、臃腫的時候,module 可以將 store 分割成各個模塊,每個模塊中擁有自己的 state、mutation、action 和 getter。
vuex 頁面刷新數據丟失的解決辦法
在 vue 項目中用 vuex 來做全局的狀態管理, 發現當刷新網頁后,保存在 vuex 實例 store 里的數據會丟失。參考鏈接
原因:
因為 store 里的數據是保存在運行內存中的,當頁面刷新時,頁面會重新加載 vue 實例,store 里面的數據就會被重新賦值初始化
解決思路:
將 state 的數據保存在 localstorage、sessionstorage 或 cookie 中([三者的區別](https://stackoverflow.com/questions/19867599/> what-is-the-difference-between-localstorage-sessionstorage-session-and-cookies)),這樣即可保證頁面刷新數據不丟失且易於讀取。
1.localStorage: localStorage 的生命周期是永久的,關閉頁面或瀏覽器之后 localStorage 中的數據也不會消失。localStorage 除非主動刪除數據,否則數據永遠不會消失。
2.sessionStorage:sessionStorage 的生命周期是在僅在當前會話下有效。sessionStorage 引入了一個“瀏覽器窗口”的概念,sessionStorage 是在同源的窗口中始終存在的數據。只要這個瀏覽器窗口沒有關閉,即使刷新頁面或者進入同源另一個頁面,數據依然存在。但是 sessionStorage 在關閉了瀏覽器窗口后就會被銷毀。同時獨立的打開同一個窗口同一個頁面,sessionStorage 也是不一樣的。
3.cookie:cookie 生命期為只在設置的 cookie 過期時間之前一直有效,即使窗口或瀏覽器關閉。 存放數據大小為 4K 左右,有個數限制(各瀏覽器不同),一般不能超過 20 個。缺點是不能儲存大數據且不易讀取。
由於 vue 是單頁面應用,操作都是在一個頁面跳轉路由,因此 sessionStorage 較為合適,原因如下:
1.sessionStorage 可以保證打開頁面時 sessionStorage 的數據為空;
2.每次打開頁面 localStorage 存儲着上一次打開頁面的數據,因此需要清空之前的數據。
vuex 中 state 數據的修改必須通過 mutation 方法進行修改,因此 mutation 修改 state 的同時需要修改 sessionstorage,問題倒是可以解決但是感覺很麻煩,state 中有很多數據,很多 mutation 修改 state 就要很多次 sessionstorage 進行修改,既然如此直接用 sessionstorage 解決不就行了,為何還要用 vuex 多此一舉呢? vuex 的數據在每次頁面刷新時丟失,是否可以在頁面刷新前再將數據存儲到 sessionstorage 中呢,是可以的,beforeunload 事件可以在頁面刷新前觸發,但是在每個頁面中監聽 beforeunload 事件感覺也不太合適,那么最好的監聽該事件的地方就在 app.vue 中。
在 app.vue 的 created 方法中讀取 sessionstorage 中的數據存儲在 store 中,此時用 vuex.store 的 replaceState 方法,替換 store 的根狀態
在 beforeunload 方法中將 store.state 存儲到 sessionstorage 中。
代碼如下:
export default { name: 'App', created() { //在頁面加載時讀取sessionStorage里的狀態信息 if (sessionStorage.getItem('store')) { this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem('store')))) } //在頁面刷新時將vuex里的信息保存到sessionStorage里 window.addEventListener('beforeunload', () => { sessionStorage.setItem('store', JSON.stringify(this.$store.state)) }) }, }