每一个 Vuex应用的核心就是store,而每一个store又是一个Vue的Store对象的实例,所以我们可以在根组件注入store然后通过this.$store
访问的store实例。简单的来说,它也是一个普通的js对象。这一点和redux相似。
1.vuex数据模式
vuex的设计思想借鉴了Flux、Redux、和 The Elm Architecture,所以和redux有许多相似之处,在vuex中,更改state只能通过mutation一种途径,vue组件可以dispatch异步的Action,Action通过commit同步的mutation来更改state,我们也可以通过this.$store来获取单一实例,当需要操作多个状态时,通常使用辅助函数mapState、mapMutations、mapActions,详见官文
2.基本配置
1 2 3 4 5 6 7 8 9 10 11 12 const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: {}, getters: {} })
state: 初始全局状态值
mutations: 同步处理状态值
actions: 异步数据流处理
getters: 加工处理状态值
3.模块化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import Vue from 'vue' ;import router from './router' ;new Vue ({ router, store, }).$mount ('#app' ); import Vue from 'vue' import Vuex from 'vuex' import module1 from './modules/module1' import module2 from './modules/module2' Vue.use(Vuex) export default new Vuex.Store({ modules: { module1, module2 } })
4.State状态
在组件中获取state
由于vuex存储的状态是响应式的,我们获取状态时都应该使用计算属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import store from './store' const Counter = { template: `<div>{{ count }}</div>` , computed: { count () { return store.state.count } } } const Counter = { template: `<div>{{ count }}</div>` , computed: { count () { return this .$store.state.count } } } computed: mapState({ count: state => state.count, countAlias: 'count' , countPlusLocalState (state) { return state.count + this .localCount } }) computed: mapState([ 'count' ])
5.Mutation
更改Vuex中state的唯一方式就是提交mutation,它接受state作为第一个参数。
5.1常用的Mutation方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state) { // 变更状态 state.count++ } } }) // 调用 store.commit('increment')
5.2提交参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // ... mutations: { increment (state, n) { state.count += n } } // 调用 store.commit('increment', 10) // 对象风格传参 store.commit({ type: 'increment', amount: 10 }) // 调用 mutations: { increment (state, payload) { state.count += payload.amount } }
5.4组件中调用mutation
所有的store实例都可以通过this.$store获取,这里对这种方式不做过多诠释,主要是使用辅助函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import { mapMutations } from 'vuex' export default { methods: { ...mapMutations([ 'increment' , 'incrementBy' ]), ...mapMutations({ add: 'increment' }) } }
6.Action
Action类似于mutation,但不同的是Action提交的是mutation,Action可以包含异步操作,下面案例在actions中使用commit方法调用mutations的方法实现state的更改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state, n) { state.count += n }, redce (state, n) { state.count -= n } }, actions: { addAction(context){ context.commit('increment' ,10 ) }, reduceAction({commit}){ commit('reduce' , 1 ) } }, })
组件内使用actions,我们只需要使用vuex提供的辅助函数(mapMutations和mapActions)即可映射对应的actions。
1 2 3 4 5 6 7 8 9 10 11 12 13 import { mapMutations, mapActions } from 'vuex' export default { methods:{ ...mapMutations([ 'increment' ,'reduce' ]), ...mapActions([ 'addAction' ,'reduceAction' ]) }, }
7.Getter
有时我们需要把某些state进行筛选过滤等处理,Getter就派上了用场,想当于组件的计算属性,只有当它依赖的值发生改变时才触发重新计算。
7.1通过属性访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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) } } }) store.getters.doneTodos computed: { doneTodosCount () { return this .$store.getters.doneTodosCount } }
7.2通过方法访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 const store = new Vuex.Store({ state: { todos: [ { id : 1 , text : '...' , done : true }, { id : 2 , text : '...' , done : false } ] }, getters: { getTodoById: (state ) => (id ) => { return state.todos.find(todo => todo.id === id) } } }) store.getters.getTodoById(2 ) computed: { doneTodosCount () { return this .$store.getters.getTodoById(2 ) } }
7.3mapGetters辅助函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import { mapGetters } from 'vuex' export default { computed: { ...mapGetters([ 'doneTodosCount' , 'anotherGetter' , ]) } } mapGetters({ doneCount: 'doneTodosCount' })