1. 在app.vue的created方法中讀取sessionstorage中的數據存儲在store中,此時用vuex.store的 replaceState方法,替換store的根狀態
2. 在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)) }) } }
vuex的熱門實例方法其實就2個,commit和dispatch,冷門方法倒是不少,雖然你可能一輩子不用都不妨礙開發一個牛逼的項目,但是有些功能你學了或許真的能用上。
官方文檔:https://vuex.vuejs.org/zh/api/#vuex-store-實例方法
replaceState
官方文檔就一句話,替換 store 的根狀態,僅用狀態合並或時光旅行調試。
。
狀態合並
看這段代碼:
if (sessionStorage.getItem("store")) { this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem("store")))) console.log('正在從sessionStorage恢復store') console.log(this.$store.state) sessionStorage.removeItem("store") }
我們經常遇到一個問題就是,刷新頁面導致狀態丟失,一個解決方案就是使用sessionStorage隨時儲存state,刷新頁面出發created則判斷sessionStorage.state是否有內容,有則覆蓋原state。
這里注意:
-
replaceState是覆蓋state,合並的工作要使用Object.assign(),當然了,大部分時候並不需要合並,因為sessionStorage里的就是最新的state,直接覆蓋就行了。
-
盡量避免使用這個方法,在錯誤的位置使用這個方法會造成數據被錯誤覆蓋,只應該在非常有必要恢復state的時候才使用,更多的時候,如果用戶刷新頁面,應讓用戶從頭走操作流程,只有在連續答題、購物等少數場合需要用到,而且並不是必須使用,依然有其他變通方法。
時光旅行調試
時光旅行調試是指devtools提供的時光旅行調試,這里提到時光旅行調試,我其實不太明白其中的意思,可能的意思有兩個,不是一就是二:
-
devtools自己調用replaceState方法來時光旅行,無需開發者寫任何代碼。
-
開發者在某些代碼位置覆蓋state,這種可能性比較小。
watch
官方文檔是:
watch(fn: Function, callback: Function, options?: Object): Function
響應式地偵聽fn
的返回值,當值改變時調用回調函數。fn
接收 store 的 state 作為第一個參數,其 getter 作為第二個參數。最后接收一個可選的對象參數表示 Vue 的vm.$watch
方法的參數。
要停止偵聽,調用此方法返回的函數即可停止偵聽。
這個方法的作用就是監聽state或是getters的變化,它實際上跟vue實例的watch作用差不多,比如state有一個狀態叫a:
created() { this.$store.watch((state, getter) => { return state.a }, (newVal) => { console.log('變成了', newVal); }); },
只要state的a有變化,就會被監聽到。
vue實例的watch也可以監聽state或是getters的變化,區別大約是:
-
vue實例的watch監聽更傾向於監聽data的變化
-
vuex實例的watch監聽state似的代碼更容易維護
所以vuex實例的watch可用可不用。
subscribe
官方文檔:
subscribe(handler: Function): Function
訂閱 store 的 mutation。handler
會在每個 mutation 完成后調用,接收 mutation 和經過 mutation 后的狀態作為參數:store.subscribe((mutation, state) => { console.log(mutation.type) console.log(mutation.payload) })
要停止訂閱,調用此方法返回的函數即可停止訂閱。
通常用於插件。詳細介紹
比如:
state: { a: '1' }, mutations: { SET_A(state, n) { state.a += n; }, },
created() { this.$store.subscribe((mutation, state) => { console.log('mutation.type', mutation.type) console.log('mutation.payload', mutation.payload) console.log('state.a', state.a) }); }, methods: { x() { this.$store.commit('SET_A', 3); console.log(this.$store.state.a); } }
現在執行this.x()
,得到:
mutation.type SET_A
mutation.payload 3
state.a 13
13
可見,subscribe的回調函數的執行先於this.$store.commit()之后的代碼。
subscribe的用途比如為mutation添加統一的回調函數等等,還是蠻有用的。
subscribeAction
跟subscribe類似,
actions: { ACTION_A(context, n) { console.log('ACT_A run'); context.commit('SET_A', n); } },
this.$store.subscribeAction((action, state) => { console.log('action.type', action.type) console.log('action.payload', action.payload) console.log('state.a', state.a) });
得到:
action.type ACTION_A
action.payload 3
state.a 1
ACT_A run
13
可見,subscribeAction的回調函數會在ACTION_A的所有代碼之前執行,如果想改成之后執行,需要按照官網手冊改成after對象:
this.$store.subscribeAction({after: (action, state) => { console.log('action.type', action.type) console.log('action.payload', action.payload) console.log('state.a', state.a) }});
得到:
ACT_A run
13
action.type ACTION_A
action.payload 3
state.a 1
可見,subscribeAction的回調函數不僅僅是落后於ACTION_A,甚至比this.$store.dispatch()后面的同步代碼還要落后。
registerModule和unregisterModule
registerModule用來動態注冊一個新的module,也是只在插件中使用,因為但凡你能寫死module,也犯不着動態注冊,一旦必須動態注冊,一定是在外部插件中使用。
unregisterModule用於反注冊module。
這兩個方法就不細說了,因為https://vuex.vuejs.org/zh/guide/modules.html#模塊動態注冊說的很清楚。
hotUpdate
這個方法除非是Vue.js的高級開發者,不然真的用不上,手冊在https://vuex.vuejs.org/zh/guide/hot-reload.html,我目前也只是在學習中,就不多說了。
總結
這幾個方法,我個人理解的學習優先級由高到低是:
-
subscribe、subscribeAction
-
watch
-
replaceState
-
其他
replaceState、watch、subscribe、subscribeAction這幾個不在插件中也依然好用,可以在恰當場合下使用。