Vuex的Mutation学习

Vuex 的 Mutation 学习

  更改 Vuex 的 store 中的状态的唯一方法提交 mutation
  Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)


目录:

  • Vuex 的 Mutation 学习
    • 例子
    • 将 store 注入到每个子组件
    • 提交载荷(Payload)
    • 对象风格的提交方式
    • mapMutations 辅助函数
    • Mutation 需遵守 Vue 的响应规则
    • 注意


例子

  新建一个 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>

将 store 注入到每个子组件

  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>

提交载荷(Payload)

  可以向 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
    }
}

mapMutations 辅助函数

  可以在组件中使用 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')`
        })
    }
}   

Mutation 需遵守 Vue 的响应规则

  既然 Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:

  • 最好提前在你的 store 中初始化好所有所需属性。
  • 当需要在对象上添加新属性时,你应该:
    • 使用 Vue.set(obj, ‘newProp’, 123), 或者
    • 以新对象替换老对象。例如,利用 stage-3 的对象展开运算符我们可以这样写:state.obj = { …state.obj, newProp: 123 }

注意

  一条重要的原则就是要记住 mutation 必须是同步函数

你可能感兴趣的:(vue)