Vuex is a state management pattern + library for Vue.js applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion.html
能夠理解爲,Vuex 爲 VUE 提供一套經過狀態共享實現的組件通訊方案。vue
父組件經過 props 向子組件傳值,而且監聽子組件的自定義事件。git
首選通訊方式,由於它是一種低耦合的方式。但在特定場景下有幾個不足:github
它是一個典型的單向數據流,父組件不能主動觸發子組件的事件vue-router
非父子組件中通訊,能夠經過父組件作橋樑,可是這樣父組件容易變得很臃腫,被高度耦合vuex
在 Vue 1.0 中用來解決上面第一點不足redux
在 Vue 2.0 已經廢棄,不建議使用。在特定場景下有幾點不足:架構
傳播效率比較低,組件樹越深,枝葉越多,效率也會越低app
傳播方向單一,實現非父子關係的組件通訊代價太大異步
Vue 2.0 廢棄 dispatch 和 broadcast 時,建議使用event bus 做爲一種替代方案。
它是經典的發佈訂閱模式。經過 Vue 實現十分簡單(固然,本身實現也很容易):
// 建立消息中心 const bus = new Vue() // 假設調用雙方已經約定一個名爲 myEvent 消息以及傳值方式 // 訂閱 bus.$on('myEvent',value=>{ alert(value) }) // 發佈 bus.$emit('myEvent','ok')
它是一種徹底基於事件的方式來傳值,在特定場景下有點不足:
消息容易重名
爲了減小消息愈來愈多,致使消息重名,應該根據不一樣的通訊範圍,依賴獨立的消息中心,各自管理各自的消息,減小影響範圍。
Multiple views may depend on the same piece of state.
操做重複且冗餘,同一個狀態被分散在不一樣地方,不方便管理。
<div>{{shareData.a}}</div> <c1></c1> <c2></c2>
const obj = {a: 1, b: 2} new Vue({ el: 'body', data:{ shareData:obj }, compoments:{ c1:{ template:` <div>{{shareData.a}}</div> `, data(){ return { myData:1, shareData:obj } } }, c2:{ template:` <div>{{shareData.a}}</div> `, data(){ return { myData:2, shareData:obj } } } } })
父組件經過 props 傳一個引用類型給子組件也能夠達到一樣的效果。
它像是裸奔的Vuex,只共享了狀態,在複雜的場景下難以預測狀態在什麼狀況下會發生變化,致使追蹤問題困難、維護成本增長。
有待研究
和 Vuex 的原理相近,不做討論
基於以上的一些不足,Vuex 正好能夠用來解決那些痛點。
那麼 Vuex 有哪些不足呢?
它是基於數據共享的,那麼顯而易見,共享的越多,代碼的耦合度約高,這就是在使用Vuex的時候須要去平衡的地方。
在什麼場景下建議使用 Vuex ?
引入 Vuex 後的會有哪些變化?
Vuex 的版本如何選擇?
如何區分和理解 actions 和 mutations 的使用場景?
如何定義 state ?
經過以上的分析,能夠得出一個大體的結論,Vuex 解決了其餘方案沒有解決的問題,其實也正好是它的應用場景 —— 兩個以上組件共享數據。
官方文檔這樣描述了這樣一個場景
Multiple views may depend on the same piece of state.
Actions from different views may need to mutate the same piece of state.
官方文檔所描述的場景多組件共享數據的狀況。
若是是兩個非父子組件之間徹底能夠用 event bus 實現。
若是應用中有一些是兩個以上的組件共享數據,有些是兩個非父子組件共享數據,那麼,是所有用Vuex 仍是 Vuex 和 event bus 混合用呢?
若是是三個組件共享數據,而又有一個不少表單交互,是否值得爲雙向綁定,增長額外的代碼量?
Vue 最經典的一個例子,莫過於在表單元素上作的雙向綁定。
而 Vuex 核心概念是單向數據流,必須遵循
Vuex 給咱們帶來一套數據管理解決方案的,同時在必定程度上犧牲掉一部分靈活性,增長了代碼量。
簡單的能夠認爲,通用組件不該該和 Vuex 關聯起來,只經過 prop event 通訊
出於如下幾點,最終選擇了 Vuex 2.0
當前我正在使用 Vue 1.0.28 開發項目,下意識的認爲 Vuex 應該和 Vue-router 同樣:
This is vue-router 2.0 which works only with Vue 2.0. For the 1.x router see the 1.0 branch.
在官方資料中也沒有找到相關說明提示,最後,作了一個 demo 加入 Vuex 2.0.0 和 Vue 1.0.28 一塊兒運行,測試結果沒有發現跨版本的兼容問題。
排除了兼容問題。
理念仍是單向數據流,
2.0 中有幾個很重要的變化,使得代碼結構變得更清晰:
經過 store.dispatch
觸發 actions
媽媽不再用擔憂我在 `methods` 中定義的方法名和 `actions` 中的重名了
(略了,有空補充)
能夠看看知乎上做者的回答
區分 actions 和 mutations 並非爲了解決競態問題,而是爲了能用 devtools 追蹤狀態變化。
事實上在 vuex 裏面 actions 只是一個架構性的概念,並非必須的,說到底只是一個函數,你在裏面想幹嗎均可以,只要最後觸發 mutation 就行。異步競態怎麼處理那是用戶本身的事情。vuex 真正限制你的只有 mutation 必須是同步的這一點(在 redux 裏面就好像 reducer 必須同步返回下一個狀態同樣)。
既然設計出來,個人理解能夠這樣使用:
異步操做自然要定義成 action
能夠把 mutation 看做單一職責,actions 是 mutation 的組合體
也就是說,若是多個函數對 state 作了一樣的操做,應該把這些操做提取出來,放到 mutation 中,這些函數定義成 action
// a 模塊 const a =[{ id:1, isShow:true, aName:'a1' },{ id:2, isShow:false, aName:'a2' }]; // b 模塊 const b =[{ id:1, isShow:true, bName:'b1' },{ id:2, isShow:false, bName:'b2' }]; // c 模塊 const b =[{ id:1, isShow:true, cName:'c1' },{ id:2, isShow:false, cName:'c2' }];
三個模塊對應 id 同步 isShow 的狀態,那麼問題來了 state 應該怎麼定義?
// 方案1 const a= null; const b= null; const c= null; const state =[{ id:1, isShow:true, aName:'a1', bName:'b1', cName:'c1' },{ id:2, isShow:false, aName:'a1', bName:'b2', cName:'c2' }] // 方案2 const a =[{ id:1, aName:'a1' },{ id:2, aName:'a2' }]; const b =[{ id:1, bName:'b1' },{ id:2, bName:'b2' }]; const c =[{ id:1, cName:'c1' },{ id:2, cName:'c2' }]; const state =[{ id:1, isShow:true },{ id:2, isShow:false }]
我會選擇方案2,理由是共享該共享的,不該該共享多餘的數據。
可是糾結的是方案1,維護性看上去更好,而擴展起來沒有方案2靈活。
Vuex 歷經了 0.x 、 1.x(沒有出正式版直接跳2.0了) 到如今的2.0正式版,不說翻天覆地,卻也是變化至關大。
先看了幾遍 1.0 的中文文檔,把單項數據流
等一些概念簡單學習,把 Vuex 想幹什麼,能幹什麼以及一些理念瞭解下,再簡單寫了個例子就算是入門了。
要注意的是,中文文檔不是做者翻譯的,並且後續的巨大的變動沒有及時更新
,固然,用它作一份中文入門資料仍是不錯的。
有了以前的入門基礎後,能夠更好理解的英文文檔的一些概念,閱讀起來不會太吃力。
固然,在知乎上有一些做者關於 Vuex 的回答,對理解 Vuex 有必定的幫助。
感受 avalon = Vue + Vuex。