Vuex 的學習記錄
- 資料參考網址
- Vuex的簡介
- Vuex 是一個類似 Redux 的狀態管理器,專為 Vue.js 應用程序開發,采用集中式存儲管理應用的所有組件的狀態,并以相應的規則保證狀態以一種可預測的方式發生變化,并集成到了Vue的官方調試工具 devtools extension
- Vuex的使用情況: 當開發大型單頁面應用(SPA)時,會出現多個視圖組件依賴同一個狀態,來自不同視圖的行為需要變更同一個狀態。
- 基礎使用及API說明
-
常用api及基礎寫法
// func 指代 Function,函數 const store = new Vuex.Store( { state: {} | func, // 根state對象,初始數據或狀態賦值 mutations: {}, // 純函數修改數據的方法,處理函數總是接受 state 作為第一個,payload 作為第二個參數(可選) actions: {}, // 事件,動作, 處理函數總是接受 context 作為第一個參數,payload 作為第二個參數(可選)。 getters: {}, // store 的計算屬性,返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生改變才會被重新計算 modules: {}, // 包含子模塊的對象,會被合并到 store plugins: [], // 包含應用在store上的插件方法,這些插件接受store作為唯一參數,可以監聽 mutation(用于外部地數據持久化、記錄或調試)或者提交 mutation(用于內部數據,例如 websocket 或 某些觀察者) strict: Boolean, // 默認值:false, 使Vuex store進入嚴格模式,任何 mutation 處理函數以外修改 Vuex state 都會拋出錯誤。 } );
-
最簡單的 Vuex 示例
``` import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } } }); store.commit('increment'); console.log(store.state.count) // 1 ``` 注明:每一個Vuex應用就是一個store,在store中包含組件的共享狀態 `state` 和改變狀態的方法 `mutations`,且只能通過 `mutations` 改變store的 `state` 的狀態,不能通過類似 `store.state.count = 5` 的方式直接更改(直接修改,狀態不會被同步,組件也不會重新渲染)
-
在Vue組件使用Vuex
- 在<b>根組件</b>,將store 注入到每一個子組件中,在子組件就可以通過
this.$store
訪問:
// 根組件 import store from './store'; new Vue({ el: '#app', router, store, render: h => h(App) }) // Counter 組件 export default { name: 'counter', computed: { count () { return this.$store.state.count } } }
- <b>Getters</b>: Vuex 中
getters
對象,接受state作為第一個參數,可以方便我們在 store 對 state 進行處理計算。Getter也可以接受其他 <b>getters</b> 作為第二參數
const store = new Vuex.Store({ state: { todos: [ { id: 1, text: '...', done: true }, { id: 2, text: '...', done: false } ] }, getters: { doneTodos: state => { return state.todos.filter(todo => todo.done) } } }) // 在Vue中通過 store.getters對象調用 computed: { doneTodos () { return this.$store.getters.doneTodos } } // Getter也可以接受其他getters作為第二個參數 getters: { doneTodos: state => { return state.todos.filter(todo => todo.done) }, doneTodosCount: (state, getters) => { return getters.doneTodos.length } }
- <b>Mutations</b>: 每一個mutation都有一個事件類型type和一個回調函數handler,
Mutations
必須是同步函數,若需要異步操作,就需要Actions
了。
const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state) { state.count++; // 變更state狀態 } } }) // 調用mutation,需要通過store.commit方法調用mutation type store.commit('increment'); // 可以向store.commit傳入第二參數,也就是mutation的payload(多數情況傳對象) mutaion: { increment (state, n) { state.count += n; }, outcrement (state, payload) { state.totalPrice += payload.price + payload.count; } } store.commit('increment', 10); store.commit('outcrement', { price: 10, count: 8 });
- 在<b>根組件</b>,將store 注入到每一個子組件中,在子組件就可以通過
-
-
- Vuex.Store 組件綁定的輔助函數
-
mapState(namespace?: string, map: Array<string> | Object), 第一個參數可選。當一個組件需要獲取多個狀態的時候,將這些狀態都聲明為計算屬性會有些重復和冗余。使用
mapState
輔助函數可以幫助我們批量生成計算屬性。// 在單獨構建的版本中輔助函數為 Vuex.mapState import { mapState } from 'vuex' export default { computed: mapState({ // 箭頭函數可使代碼更簡練 count: state => state.count, // 不使用mapState輔助函數的寫法 // 傳字符串參數 'count' 等同于 `state => state.count` countAlias: 'count', // 寫法一,使用別名方式 // 為了能夠使用 `this` 獲取局部狀態,必須使用常規函數 countPlusLocalState (state) { return state.count + this.localCount // 寫法二,常規函數方式 } // }) } // 當映射的計算屬性的名稱與state的子節點名稱相同時,可用字符串數組的寫法 export default { computed: mapState(['count']) // 映射 this.count 為 store.state.count } // 使用 ES6 的 對象展開運算符 的寫法去簡化 export default { computed: { ...mapState(['count','total']) } }
- mapGetters(namespace?: string, map: Array<string> | Object) : 將 store 中的 getter 映射到局部計算屬性。
import { mapGetters } from 'vuex' export default { computed: { // 使用對象展開運算符將 getter 混入 computed 對象中 ...mapGetters([ 'doneTodosCount', 'anotherGetter' ]) } } // 想將getter屬性另取一個名字,需使用對象形式 export default { computed: { mapGetters({ doneCount: 'doneTodosCount' // 映射 `this.doneCount` 為`store.getters.doneTodosCount` }) } }
- mapActions(namespace?: string, map: Array<string> | Object): 將組件的 methods 映射為 store.dispatch 調用
import { mapActions } from 'vuex' export default { methods: { ...mapActions([ 'increment', // 將 `this.increment()` 映射為 `this.$store.dispatch('increment')` // `mapActions` 也支持載荷: 'incrementBy' // 將 `this.incrementBy(amount)` 映射為 `this.$store.dispatch('incrementBy', amount)` ]), ...mapActions({ add: 'increment' // 將 `this.add()` 映射為 `this.$store.dispatch('increment')` }) } }
- mapMutations(namespace?: string, map: Array<string> | Object): 將組件中的 methods 映射為 store.commit 調用
import { mapMutations } from 'vuex' export default { methods: { ...mapMutions([ 'increment', // 將`this.increment()` 映射為 'this.$store.commit('increment')' // `mapMutations` 也支持載荷: 'incrementBy' // 將 `this.incrementBy(amount)` 映射為 `this.$store.commit('incrementBy', amount)` ]), ...mapMutations({ add: 'increment', // 將 `this.add()`映射為`this.$store.commit('increment')` }) } }
-
createNamespacedHelpers(namespace: string): 建基于某個命名空間輔助函數
import { createNamespacedHelpers } from 'vuex' const { mapState, mapActions } = createNamespacedHelpers('some/nested/module') export default { computed: { // 在 `some/nested/module` 中查找 ...mapState({ a: state => state.a, b: state => state.b }) }, methods: { // 在 `some/nested/module` 中查找 ...mapActions([ 'foo', 'bar' ]) } }
-
- Vuex.Store 的實例屬性
store.commit( '', { } ) : 提交 mutation
store.dispatch( '', { } ) : 分發 actions
store.replaceState(newstate): 替換 store 的根狀態,僅用狀態合并或時光調試。
store.watch( getter, cb ) : 響應式地監測一個 getter 方法的返回值,當值改變時調用回調函數。
-
store.subscribe(Function): 注冊監聽 store 的 mutations , Function 會在每個 mutations 完成后調用,接受 mutation 和 經過 mutation 后的狀態作為參數:
store.subscribe((mutation, state) => { console.log(mutation.type) console.log(mutation.payload) })
-
store.subscribeAction(handler: Function): 訂閱 store 的action, handler 會在分發的時候調用并接收 action 描述和當前的 store 的 state兩個參數。
store.subscribeAction((action, state) => { console.log(action.type) console.log(action.payload) })