怎么解決vuex頁面刷新數據丟失問題,以及vuex冷門知識


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。

這里注意:

  1. replaceState是覆蓋state,合並的工作要使用Object.assign(),當然了,大部分時候並不需要合並,因為sessionStorage里的就是最新的state,直接覆蓋就行了。

  2. 盡量避免使用這個方法,在錯誤的位置使用這個方法會造成數據被錯誤覆蓋,只應該在非常有必要恢復state的時候才使用,更多的時候,如果用戶刷新頁面,應讓用戶從頭走操作流程,只有在連續答題、購物等少數場合需要用到,而且並不是必須使用,依然有其他變通方法。

時光旅行調試

時光旅行調試是指devtools提供的時光旅行調試,這里提到時光旅行調試,我其實不太明白其中的意思,可能的意思有兩個,不是一就是二:

  1. devtools自己調用replaceState方法來時光旅行,無需開發者寫任何代碼。

  2. 開發者在某些代碼位置覆蓋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這幾個不在插件中也依然好用,可以在恰當場合下使用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM