vuex刷新页面数据丢失怎么解决_你是否真正了解Vuex
很久不寫文章了,斷了有一年多。這期間加入了新的團隊做leader,認識新的朋友,迎接新的挑戰。本應該坐下來整理自己的所見與所得,但又擔心是否會起到作用,是否大家會認同。就像以前有一個朋友問我寫這么多入門的文章有用嗎?還有一些文章好像在自說自話。
其實還真是這樣,反觀自己的文章,其實大部分是自己寫給自己的。越長大越孤單,很多想法,很多疑問,很多心里話其實是通過文章間接的與自己溝通。換個角度審視自己的行為與思想。
我也盡可能的想通過自己的文章傳達一些技術之外的東西,要明白 “授之以魚不如授之以漁”。除了技術技巧之外,有什么東西可以受用一生,可以幫助你更快掌握知識點,更快實現目標?我有很多要整理的內容,不放在這里細說,后面我會整理一下自己關于項目管理,團隊管理,前端工作流,前端組件化,前端模板化,前端直播的一些成果,在這里和大家分享。
好了,回歸正題,今天我們聊一聊 Vuex。看看大家是否真正完全掌握了 Vuex。過去一段時間,我發現大部分同學對技術的理解沒有到達一定深度。只是停留在簡單的知識點上,并沒有深入的去進行思考。這就導致很多知識點其實并沒有完全掌握。隨便找一個方向進行深入發問,就會觸到你的知識盲區。今天我們就對 Vuex 的各個點進行發問,以一個初學者的角度來重新認識下 Vuex
下面的內容中我會用各種問題來進行串聯,請大家遇到我的提問時能先簡單做下思考。有了結果后再看我的答案。我說的是我的理解,不一定就是對的,希望你也有自己的看法和理解,我的答案只是你心中的答案一個對照。
什么是 Vuex?
在官網的介紹中這樣寫到:
“Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件的狀態,并以相應的規則保證狀態以一種可預測的方式發生變化。”我們去了解一個技術方案時,第一步應該想清楚 “這個方案解決什么樣的問題?”
Q: 那么第一個問題來了, Vuex 是為了解決什么問題呢?是什么樣的問題讓我們必須要用 Vuex 解決呢?
A: 我們說 Vue.js 是單向數據流模型。在單頁面應用中,數據由父組件向子組件進行傳遞,子組件通過觸發父組件事件的方式可以進行數據回傳。想象這樣一個場景,如果頁面有復雜的組件嵌套,并且嵌套層次可能很深。這種情況下我們的數據需要通過 prop 一級一級向下傳遞,葉子組件的事件需要一級一級向上觸發。這樣的方式顯然是不好的,我們希望父組件能夠更方便的與各個子孫組件進行通信。再想象一個場景,單頁面多路由的情況下,A頁面需要傳遞數據給B頁面,我們如何做路由間的數據傳遞呢?按照以往的解決方案,一般會選擇 storage,cookie或者url攜帶參數來解決。這種方案也存在數據安全,數據傳遞大小限制等問題。以上的問題有沒有一個更優雅的解決方案呢?
Q: 如果讓你來解決以上的問題,不使用現有框架,有什么好的辦法嗎?
A: 如果我來實現,我會在window下設置一個變量,值為一個空對象。可以將所有需要傳遞的變量數據存儲在這個對象中。通過 Object.defineProperty 對所有屬性添加 set 監聽,每當屬性值發生變化時 通過 window.dispatchEvent 觸發一個全局事件。該事件注冊到所有組件中,每當屬性變化時通知到各個頁面與組件,再由各個組件進行取出單獨處理。
我們再看下Vuex是不是這樣做的,Vuex的核心結構包括:State,Getter,Mutation, Action, Module。我們把 State 看作是那個存儲全部共享數據的對象。當你需要跨路由,跨組件進行數據共享時,把需要共享的數據保存到 State 中即可。Vuex 框架會幫你進行同步,只要有修改就會同步到各個組件中。并及時更新頁面數據。
數據設置好之后,我們就可以在各個組件中使用 this.$store.state 來獲取 state 對象并使用數據。當你需要修改數據時,你需要觸發一個 mutation 來進行數據修改,官網的示例我們看下:
const store = new Vuex.Store({state: {count: 1},mutations: {increment (state) {// 變更狀態state.count++}} })每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler), 在上面的例子中 type 為 increment當我們要修改 state 中的 count 屬性時,需要這么做:
store.commit('increment')通過觸發 mutation 下的 increment 事件來修改 對此,官網也有一句解釋:
“更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation”Q: 第三個問題來了,為什么不能直接通過 this.$store.state.count = 3 來進行賦值?為什么不能直接對 state 下的數據進行賦值?為什么一定要使用 mutation?
A: 最初提出這個問題時,我聽到兩個回答是:
“mutation 保證數據可溯源”
“mutation更明確地追蹤到狀態的變化”
在官網我找到這么一段話:
”再次強調,我們通過提交 mutation 的方式,而非直接改變 store.state.count,是因為我們想要更明確地追蹤到狀態的變化。這個簡單的約定能夠讓你的意圖更加明顯,這樣你在閱讀代碼的時候能更容易地解讀應用內部的狀態改變。此外,這樣也讓我們有機會去實現一些能記錄每次狀態改變,保存狀態快照的調試工具。有了它,我們甚至可以實現如時間穿梭般的調試體驗。“按照文檔內容,上面的兩個回答是沒問題的。我們可以引申另一個問題:
Q: 數據為什么要溯源?為什么要記錄每次狀態改變?為什么要保存狀態快照?
A: 首先,通過 this.$store.state.count 進行賦值是沒有任何問題的,在非嚴格模式下這么寫不會報錯,數據修改可以被監聽到。為什么非要使用 mutation 使數據可溯源呢?試想:
當我在A頁面使用 this.$store.state.count = 10;
然后在B頁面再次修改 this.$store.state.count = 3;
你是否可以觀察到這個修改順序?你不能,你只能看到修改的結果是 count 值為3,并不知道過程中是誰修改了他。為了在調試工具中觀察到數據變化過程,我們統一使用 mutation 來修改數據,會有一個log系統記錄下你的每一次修改,如圖:
理解了為什么必須使用 mutation 更新數據后,我們再來看一看 mutation 還有什么問題。在官網對 mutation 的介紹中有這么一句話:
”一條重要的原則就是要記住 mutation 必須是同步函數。“Q: 為什么 mutation 必須是同步函數?我在接口請求的異步回調中執行 store.commit('increment') 可以嗎?
A: 首先,官網的 mutation 必須是同步函數,是要求 mutation 下的每個事件的回調函數必須是同步代碼。對 commit 觸發事件的時機并沒有要求,也就是你可以在任意異步方法中執行 store.commit() 來修改數據。為什么 mutation 的事件回調必須是同步代碼呢?其實還是為了保證溯源的準確性,當遇到下面情況時:
store.commit('A'); store.commit('B'); store.commit('B');我們希望觀察數據變化時,log中能體現正確的執行順序:A -> B -> C。當這其中任意一個方法是異步處理時,就有可能出現偏差,數據失真,加大了調試的復雜度,其結果可能是:A -> C -> B / C -> A -> B。所以這就是為什么 mutation 的事件回調必須是同步代碼。
除了 mutation 外還有一個修改 state 的辦法,就是通過 Action。Action 類似于 mutation,不同在于:
1. Action 提交的是 mutation,而不是直接變更狀態。
2. Action 可以包含任意異步操作。
也就是說 Action 是 mutation 的包裝,但是 Action 中可以執行異步代碼。代碼示例:
const store = new Vuex.Store({state: {count: 0},mutations: {increment (state) {state.count++}},actions: {increment ({ commit }) {setTimeout(() => {commit('increment')}, 1000) }} })Q: 就因為異步執行代碼就發明 actions 嗎?actions 和 mutations 為何一個可以異步一個不可以呢?actions 如何保證溯源的準確性呢?
A: 還是那句話,了解一個方案時,要先看這個方案解決什么問題。actions 解決什么問題呢?試想,一個單頁面應用下,在各個頁面都要獲取一下最新的活動數據,然后在接口請求成功后通過 store.commit('updateDialogData') 來更新全局數據。這樣做是不是很傻,我們不能在一個公共的地方寫這個數據請求嗎?
mutations 下是不可以的。所以我們提供一個 actions。這樣你就可以把之前需要寫到各個組件,各個頁面的異步代碼放到一起統一管理了。通過 this.$store.dispatch('xxx') 來觸發事件。這樣的情況下如何保證正確溯源呢?以往我們是通過 mutations 下的 type 來記錄歷史的。此處同樣可以根據 mutations 記錄真實的數據變化。但他不是原始的操作順序,原始的操作順序需要按照 actions 的觸發順序記錄。
與 actions 的做法類似,當我們每次取出 state 下的數據后都要進行一次格式化,那為什么不能在一個公共的位置統一處理呢?Getter 就是解決這個問題,內部包含了對 state 下數據的 格式化整理函數。
同理,當state上的數據堆積過多,我們需要劃分不同的數據區時,Module 可以更簡單的提供這個功能。
總結:
以上問題其實沒有任何深度,只是記錄了一次內部探討過程。分享出來與大家共同學習。我們只需要多思考就可以明白作者為什么要這么設計,這樣設計的好處是什么。但往往我們對一個知識點的深度理解就缺少這么幾個問題。多去發現問題,提出問題,解決問題。這樣才能夠快速提高,做到知其然知其所以然。
以上,與君共勉。
總結
以上是生活随笔為你收集整理的vuex刷新页面数据丢失怎么解决_你是否真正了解Vuex的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 邪神的遗产女主最强武器公式是什么 邪神的
- 下一篇: 联想笔记本如何将系统恢复成出厂系统联想笔