更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
目录:
新建一个 store.js 文件用于创建 store 实例:
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
// 回调函数会接受 state 作为其第一个参数
increment (state) {
state.count++
}
}
})
export default store
在组件 App.vue 中提交 mutation:
// App.vue
<template>
template>
<script>
import store from "./store.js";
export default {
data() {
return {}
},
created:function(){
setInterval(() => {
// 要唤醒一个 mutation handler,需要以相应的 type 调用 store.commit 方法
store.commit('increment');
console.log(store.state.count); // 1 2 3 4 ...
}, 1000);
}
}
script>
Vuex 通过 store 选项,提供了一种机制将状态从根组件“注入”到每一个子组件中(需调用 Vue.use(Vuex)):
// main.js
import Vue from 'vue'
import App from './App.vue'
import Vuex from 'vuex'
import store from './store.js'
Vue.use(Vuex); // 调用Vue.use(Vuex)
new Vue({
el: '#app',
store, // “注入”
render: h => h(App)
})
再在 App.vue 中提交 mutation:
// App.vue
<template>
template>
<script>
// import store from "./store.js"; // 现在可以不用在每个 vue 组件中导入 store 实例了
export default {
data() {
return {}
},
created:function(){
setInterval(() => {
this.$store.commit('increment');
console.log(this.$store.state.count); // 1 2 3 4 ...
}, 1000);
}
}
script>
可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload):
// store.js
mutations: {
increment (state, payload) {
state.count += payload.amount;
}
}
// App.vue
created:function(){
//载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读
store.commit('increment', {
amount: 10
});
console.log(store.state.count); // 10
}
提交 mutation 的另一种方式是直接使用包含 type 属性的对象:
// App.vue
store.commit({
type: 'increment',
amount: 10
})
// store.js
mutations: {
// 当使用对象风格的提交方式,整个对象都作为载荷传给 mutation 函数
increment (state, payload) {
state.count += payload.amount
}
}
可以在组件中使用 this.$store.commit(‘xxx’) 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。
// store.js
mutations: {
increment (state) {
state.count++
}
}
// App.vue
import { mapMutations } from 'vuex'
export default {
created:function(){
this.increment();
console.log(this.$store.state.count); // 1
},
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
// ...
]}
}
}
mapMutations 也支持载荷:
// store.js
mutations: {
increment (state, payload) {
state.count += payload.amount;
}
}
// App/.vue
import { mapMutations } from 'vuex'
export default {
created:function(){
this.increment({
amount: 10
});
console.log(this.$store.state.count); // 10
},
methods: {
...mapMutations([
'increment', // 将 `this.increment(amount)` 映射为 `this.$store.commit('increment', amount)`
// ...
]}
}
}
通过传入一个对象也可以起到起别名的作用:
// App/.vue
import { mapMutations } from 'vuex'
export default {
created:function(){
this.add({
amount: 10
});
console.log(this.$store.state.count); // 10
},
methods: {
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}
}
既然 Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:
一条重要的原则就是要记住 mutation 必须是同步函数。