vuex爲咱們提供了兩種使用方法vue
vuex下載地址:https://unpkg.com/vuex@2.0.0 es6
下載以後用< script >標籤包裹引入便可vuex
npm install vuex --save
在一個模塊化的打包系統中,您必須顯式地經過 Vue.use() 來安裝 Vuex:shell
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex)
當使用全局 script 標籤引用 Vuex 時,不須要以上安裝過程。npm
vuex就是一個狀態(數據)管理工具,每個vuex都有一個store(倉庫),store是一個容器,它包含着你的應用中大部分的狀態(state)。Vuex 和單純的全局對象有如下兩點不一樣:異步
1.Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那麼相應的組件也會相應地獲得高效更新。模塊化
2.你不能直接改變 store 中的狀態。改變 store 中的狀態的惟一途徑就是顯式地提交(commit) mutations。這樣使得咱們能夠方便地跟蹤每個狀態的變化,從而讓咱們可以實現一些工具幫助咱們更好地瞭解咱們的應用。函數
建立vuex工具
var store = new Vuex.store({ // 數據放在state中 state:{ msg:1 }, // 新建方法 mutations:{ // es6 寫法 jia(state){ state.msg++ } } }) // 調用mutation中的"jia"方法 store.commit("jia") // 查看數據狀態 console.log(store.state.msg)
再次強調,咱們經過提交 mutation 的方式,而非直接改變 store.state.count,是由於咱們想要更明確地追蹤到狀態的變化。這個簡單的約定可以讓你的意圖更加明顯,這樣你在閱讀代碼的時候能更容易地解讀應用內部的狀態改變。此外,這樣也讓咱們有機會去實現一些能記錄每次狀態改變,保存狀態快照的調試工具。有了它,咱們甚至能夠實現如時間穿梭般的調試體驗。測試
上面咱們已將vuex建立,那麼如何在組件中進行使用呢?
咱們只須要在組件中利用計算屬性rutern出store.state.msg便可,觸發變化也只是在methods裏面提交mutation.
var vm = new Vue({ el:"#box" components:{ home:{ computed:{ msg(){ return store.state.msg } }, template:` <div> {{msg}} <input type="button" @click="jia" value="+"/> </div>`, methods:{ jia:function(){ store.commit("jia") } } } } })
Vuex 使用 單一狀態樹 —— 是的,用一個對象就包含了所有的應用層級狀態。至此它便做爲一個『惟一數據源(SSOT)』而存在。這也意味着,每一個應用將僅僅包含一個 store 實例。單一狀態樹讓咱們可以直接地定位任一特定的狀態片斷,在調試的過程當中也能輕易地取得整個當前應用狀態的快照。
單狀態樹和模塊化並不衝突 —— 在後面的章節裏咱們會討論如何將狀態和狀態變動事件分佈到各個子模塊中。
computed:{ msg(){ return store.state.msg } },
由於咱們在根實例已經註冊了store,因此咱們也可使用這種寫法
computed:{ msg(){ return this.$store.state.msg } },
這樣咱們在模塊化的構建系統中,在每一個須要使用 state 的組件中就不須要頻繁地導入,而且在測試組件時不須要模擬狀態。
當一個組件須要獲取多個狀態時候,將這些狀態都聲明爲計算屬性會有些重複和冗餘。爲了解決這個問題,咱們可使用 mapState 輔助函數幫助咱們生成計算屬性,讓你少按幾回鍵:
computed: mapState({ // 箭頭函數可以使代碼更簡練 msg: state => state.msg, })
mapState 函數返回的是一個對象。咱們如何將它與局部計算屬性混合使用呢?
對象展開運算符能夠將mapstate與局部計算屬性混合使用
computed: { localComputed () { /* ... */ }, // 使用對象展開運算符將此對象混入到外部對象中 ...mapState({ // ... }) }
使用 Vuex 並不意味着你須要將全部的狀態放入 Vuex。雖然將全部的狀態放到 Vuex 會使狀態變化更顯式和易調試,但也會使代碼變得冗長和不直觀。若是有些狀態嚴格屬於單個組件,最好仍是做爲組件的局部狀態。你應該根據你的應用開發須要進行權衡和肯定。
getters能夠說是store的計算屬性,它能夠接受state做爲第一參數和其餘getters做爲第二參數來進行計算,這樣咱們就能夠在多個組件使用這個gtters而沒必要在每個組建都書寫一遍.
var store = new Vuex.store({ // 數據放在state中 state:{ msg:1 }, // 新建方法 mutations:{ // es6 寫法 jia(state){ state.msg++ } }, getters:{ jiajia(state){ state.msg+5 } } })
computed: { // 使用對象展開運算符將 getters 混入 computed 對象中 ...mapGetters([ 'jiajia', ]) }
更改 Vuex 的 store 中的狀態的惟一方法是提交 mutation。Vuex 中的 mutations 很是相似於事件:每一個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是咱們實際進行狀態更改的地方,而且它會接受 state 做爲第一個參數:
mutations:{ // es6 寫法 jia(state){ state.msg++ } },
你能夠向 store.commit 傳入額外的參數,即 mutation 的 載荷(payload):
mutations: { increment (state, n) { state.msg += n } }
提交 mutation 的另外一種方式是直接使用包含 type 屬性的對象:
store.commit({ type: 'increment', amount: 10 })
當使用對象風格的提交方式,整個對象都做爲載荷傳給 mutation 函數,所以 handler 保持不變:
mutations: { increment (state, payload) { state.msg += payload.amount } }
Action 相似於 mutation,不一樣在於:
Action 提交的是 mutation,而不是直接變動狀態。
Action 能夠包含任意異步操做。
讓咱們來註冊一個簡單的 action:
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { increment (context) { context.commit('increment') } } })
Action 函數接受一個與 store 實例具備相同方法和屬性的 context 對象,所以你能夠調用 context.commit 提交一個 mutation,或者經過 context.state 和 context.getters 來獲取 state 和 getters。當咱們在以後介紹到 Modules 時,你就知道 context 對象爲何不是 store 實例自己了。
實踐中,咱們會常常用到 ES2015 的 參數解構 來簡化代碼(特別是咱們須要調用 commit 不少次的時候):
actions: { increment ({ commit }) { commit('increment') } }