VueX
Vuex的工作流程:

actions:支持异步操作
mutations:同步操作
安装和配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({ state: { msg: '以葫为种,不假外物' }, getters: { }, mutations: { }, actions: { }, modules: { } })
|
1 2 3 4 5 6 7 8 9 10
| import Vue from 'vue' import App from './App.vue' import store from './store'
Vue.config.productionTip = false
new Vue({ store, render: h => h(App) }).$mount('#app')
|
在组件的template中使用,通过this.$store
访问到。
1 2 3 4 5
| <template> <div id="app"> <HelloWorld :msg=this.$store.state.msg /> </div> </template>
|
State的定义和使用
定义
定义同上。
mapState辅助函数
mapState可以简化代码,帮助生成计算属性。
1 2 3 4 5 6 7
| import { mapState } from 'vuex' export default { name: 'App', computed: { ...mapState(['msg']) } }
|
另一种写法:
1 2 3 4 5 6 7 8
| import { mapState } from 'vuex' export default { name: 'App', computed: mapState({ msg: state => state.msg, aliasMsg:'msg' }) }
|
如果想要在computed中访问到data中的值,必须使用普通函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| export default { name: 'App', data() { return { prefix: '不可颂其真名 ,' } }, computed: mapState({ msg: state => state.msg, AliasMsg: 'msg', Hu(state) { return this.prefix + state.msg } }) }
|
使用对象展开符和原本的computed进行合并。
下面这种情况,computed本身的Hu
会被覆盖。
1 2 3 4 5 6 7 8 9 10 11 12
| computed: { Hu() { return this.prefix }, ...mapState({ msg: state => state.msg, AliasMsg: 'msg', Hu(state) { return this.prefix + state.msg } }) }
|
Getter
场景:多个组件需要对同一个store中的数据做相同的filter操作。类似于组件内的computed。
定义
1 2 3 4 5 6 7 8 9 10 11
| export default new Vuex.Store({ state: { msg: '以葫为种,不假外物' }, getters: { frefixMsg: state => { return '颂我真名者,' + state.msg } } })
|
访问
组件中访问。
1 2 3 4 5 6
| <template> <div class="hello"> <h1>{{ msg }}</h1> <h2>{{ this.$store.getters.frefixMsg }}</h2> </div> </template>
|
getter嵌套使用
一个getter里面也可以接收其他getter作为第二个参数。但不可以递归调用自身。
1 2 3 4 5 6 7 8
| getters: { frefixMsg: state => { return '颂我真名者,' + state.msg }, AliasFixMsg: (state, getter) => { return 'second' + getter.frefixMsg } }
|
getter传参【不会缓存】
1 2 3 4 5
| getters: { customMsg: (state) => (cm) => { return cm + state.msg } }
|
1 2 3 4 5
| <template> <div class="hello"> <h2>{{ this.$store.getters.customMsg('葫天帝') }}</h2> </div> </template>
|
mapGetters辅助函数
将store中的getter映射到局部计算属性,同样支持别名。
1 2 3 4 5 6 7 8 9 10
| import { mapGetters } from 'vuex' export default { name: 'HelloWorld', props: { msg: String }, computed: { ...mapGetters(['customMsg']) } }
|
mutation【必须是同步!!!】
每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受state作为第一个参数。多个参数封装成对象作为mutation的第二个参数。
定义mutation
1 2 3 4 5 6 7 8 9 10 11
| export default new Vuex.Store({ state: { msg: '以葫为种,不假外物' }, mutations: { changeMsg(state, msg) { state.msg = msg } } })
|
组件中提交更新
1 2 3
| updateMsg() { this.$store.commit('changeMsg','葫,我的孩子,你在哪?') }
|
对象风格的提交方式。data
为commit传递的整个对象。
1 2 3 4 5
| mutations: { changeMsgObject(state, data) { state.msg = data.msg } }
|
1 2 3 4 5
| methods: { updateMsgObject() { this.$store.commit({ type: 'changeMsgObject', msg: '镇压!' }) } }
|
mapMutations
使用mapMutations可以将this.$store.commit('xxx')
映射为this.xxx
。
1 2 3 4 5 6
| methods: { updateMsg() { this.$store.commit('changeMsg', '葫,我的孩子,你在哪?') }, ...mapMutations(['changeMsg']) }
|
1 2 3 4 5
| <template> <div class="hello"> <button @click="changeMsg('善假于物')">点我修改数据</button> </div> </template>
|
Action【支持异步操作!!!】
- Action提交的是mutation,而不是直接改变状态。
- Action可以包含任意异步操作。
Action的定义
1 2 3 4 5 6 7 8
| actions: { changeMsgDelay(context, { msg, delay }) { setTimeout(() => { context.commit('changeMsg', msg) }, delay); } }
|
Action的派发
1 2 3 4 5
| methods: { asyncUpdate() { this.$store.dispatch({ type: 'changeMsgDelay', msg: '吾以葫名,号令诸天', delay: 3000 }) }, }
|
mapActions辅助函数
辅助函数将组件的methods映射为store.dispatch调用。
1 2 3
| methods: { ...mapActions(['changeMsgDelay']) }
|
1 2 3
| <template> <button @click="changeMsgDelay({ msg: '吾以葫名,号令诸天', delay: 3000 })">点我修改数据</button> </template>
|
组合Action
action可以返回一个promise,在dispatch之后使用then
回调。
Moudle
基本示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| const moduleA = { state: () => ({ ... }), mutations: { ... }, actions: { ... }, getters: { ... } }
const moduleB = { state: () => ({ ... }), mutations: { ... }, actions: { ... } }
const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } })
store.state.a store.state.b
|
对于模块内部的mutation和getter,接收的第一个参数是模块的局部状态对象。
同样,对于模块内部的action,局部状态通过context.state暴露出来,根节点状态则为context.rootState。
对于模块内部的 getter,根节点状态会作为第三个参数暴露出来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const moduleA = { actions: { incrementIfOddOnRootSum ({ state, commit, rootState }) { if ((state.count + rootState.count) % 2 === 1) { commit('increment') } } }, getters: { sumWithRootCount (state, getters, rootState) { return state.count + rootState.count } } }
|
命名空间
默认情况下,模块内部的action、mutation和getter是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。
模块具有更高的封装度和复用性,可以通过添加namespaced: true的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
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
| const moudleA = { namespaced: true, state: { anum: 0 }, getters: { getAnum(state) { return state.anum } }, mutations: { changenum(state, num) { state.num = num } }, actions: { asyncChangenum(context, num) { context.commit('changenum', num) } } } export default new Vuex.Store({ modules: { moudleA }f })
|
开启后:

命名空间的模块内访问全局
1 2
| dispatch('someOtherAction', null, { root: true }) commit('someMutation', null, { root: true })
|
命名空间内注册全局action
1 2 3 4 5 6
| actions: { someAction: { root: true, handler (namespacedContext, payload) { ... } } }
|
简化辅助函数
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
| computed: { ...mapState('some/nested/module', { a: state => state.a, b: state => state.b }) }, methods: { ...mapActions('some/nested/module', [ 'foo', 'bar' ]) }
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
computed: { ...mapState({ a: state => state.a, b: state => state.b }) }, methods: { ...mapActions([ 'foo', 'bar' ]) }
|
4.0新特性
全新的“useStore”组合式函数
1 2 3 4 5 6 7
| import { useStore } from 'vuex'
export default { setup () { const store = useStore() } }
|