Vuex Mutation


每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++
    }
  }
})
以相应的 type 调用 store.commit 方法:
store.commit('increment')

提交载荷(Payload)

store.commit 传入额外的参数 :载荷(payload)

// ...
mutations: {
  increment (state, n) {
    state.count += n
  }
}

调用:

store.commit('increment', 10)

载荷是一个对象时:

// ...
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}

调用:

store.commit('increment', {
  amount: 10
})

对象风格:

mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}

调用:

store.commit({
  type: 'increment',
  amount: 10
})


其他规则:

  1. 最好提前在你的 store 中初始化好所有所需属性。

  2. 当需要在对象上添加新属性时,你应该

  • 使用 Vue.set(obj, 'newProp', 123), 或者

  • 以新对象替换老对象。例如,利用对象展开运算符我们可以这样写:

    state.obj = { ...state.obj, newProp: 123 }

使用常量替代 Mutation 事件类型

// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'

// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'

const store = new Vuex.Store({
  state: { ... },
  mutations: {
    // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }
})

Mutation 必须是同步函数

index.js
import Vue from 'vue';
import 'es6-promise/auto'
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
    state: {
        count: 0,
        countPlus: 1,
        countLength: 1,
        productName: '',
        productPrice: 0,
        productTotal: 0,
    },
    getters: {
        countCache: function (state) {
            return state.count + state.countPlus;
        },
        countFunc: function (state) {
            return function (num) {
                return state.countPlus > num;
            }
        }

    },
    mutations: {
        increment(state) {
            state.count++;
            state.countPlus = state.count + 1;
            state.countLength = state.count.toString().length;
        },
        decrement(state) {
            state.count--;
            state.countPlus = state.count + 1;
            state.countLength = state.count.toString().length;
        },
        calculate(state, payload) {
            state.productPrice = payload.price;
            state.productName = payload.name;
            state.productTotal = state.productPrice * state.count;
        },
    },
});
export default store;


StoreComponent.vue:

<template>
    <div>
        <button @click="increment"> {{count}}</button>
        <button @click="decrement"> {{count}}</button>
        <span> Plus one: {{ countPlus }}</span>
        <span> Length:   {{ countLength}}</span>
        <span> Plus one Length:   {{ countPlusLength}}</span>
        <span> countAndCountPlusCache:   {{ countPCountPlusCache}}</span>
        <span> countAndCountPlusFunc:   {{ countPCountPlusFunc}}</span>
        <div>
            <span> countCache:   {{ countCa}}</span>
            <span> countFunc:   {{ countFu(12)}}</span>
        </div>

        <div>
            <table>
                <tr>
                    <th>Product Name</th>
                    <th>Product Count</th>
                    <th>Product Price</th>
                    <th>Product Total</th>
                </tr>
                <tr>
                    <th>{{pName}}</th>
                    <th>{{count}}</th>
                    <th>{{pPrice}}</th>
                    <th>{{pTotal}}</th>
                </tr>
            </table>
        </div>
        <div>
            <input type="text" v-model="productName">
            <input type="text" v-model="productPrice">
            <button @click="calculate">Calculate</button>
        </div>
    </div>
</template>

<script>
    import {mapState} from 'vuex';
    import {mapGetters} from 'vuex';

    export default {
        name: "StoreComponent",
        data: function () {
            return {
                productName: '',
                productPrice: 0,
            }
        },
        // computed: {
        //     count() {
        //         return this.$store.state.count;
        //     },
        //
        // },
        computed: {
            countPlusLength() {
                return this.countPlus.toString().length;
            },
            countPCountPlusCache() {
                return this.$store.getters.countCache;
            },
            countPCountPlusFunc() {
                return this.$store.getters.countFunc(2);
            },
            ...mapState({
                count: state => state.count,

                countPlus: 'countPlus',

                countLength(state) {
                    return state.countLength;
                },
                pName: 'productName',
                pPrice: 'productPrice',
                pTotal: 'productTotal',

            }),
            // 使用对象展开运算符将 getter 混入 computed 对象中
            // ...mapGetters([
            //     'countCache',
            //     'countFunc',
            // ]),


            ...mapGetters({
                // 把 `this.countCa` 映射为 `this.$store.getters.countCache`
                countCa: 'countCache',
                // 把 `this.countFu` 映射为 `this.$store.getters.countFunc`
                countFu: 'countFunc',
            }),
        },
        // computed: mapState([
        //     'count',
        //     'countPlus',
        //     'countLength',
        // ]),
        methods: {
            increment() {
                this.$store.commit('increment');
            },
            decrement() {
                this.$store.commit('decrement');
            },
            calculate() {
                let payload = {
                    price: this.productPrice,
                    name: this.productName,
                };
                // this.$store.commit('calculate', payload);

                // this.$store.commit({
                //     type: 'calculate',
                //     price: this.productPrice,
                //     name: this.productName,
                // });
            },
        }
    }
</script>

<style scoped>

</style>

效果:

vue.test vuex mutations

mapMutations 辅助函数

import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
    ...mapMutations([
      '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')`
    })
  }
}


StoreComponent.vue:

<template>
    <div>
        <button @click="increment"> {{count}}</button>
        <button @click="decrement"> {{count}}</button>
        <span> Plus one: {{ countPlus }}</span>
        <span> Length:   {{ countLength}}</span>
        <span> Plus one Length:   {{ countPlusLength}}</span>
        <span> countAndCountPlusCache:   {{ countPCountPlusCache}}</span>
        <span> countAndCountPlusFunc:   {{ countPCountPlusFunc}}</span>
        <div>
            <span> countCache:   {{ countCa}}</span>
            <span> countFunc:   {{ countFu(12)}}</span>
        </div>

        <div>
            <table>
                <tr>
                    <th>Product Name</th>
                    <th>Product Count</th>
                    <th>Product Price</th>
                    <th>Product Total</th>
                </tr>
                <tr>
                    <th>{{pName}}</th>
                    <th>{{count}}</th>
                    <th>{{pPrice}}</th>
                    <th>{{pTotal}}</th>
                </tr>
            </table>
        </div>
        <div>
            <input type="text" v-model="productName">
            <input type="text" v-model="productPrice">
            <button @click="calculate({
                type: 'calculate',
                price: productPrice,
                name: productName,})">Calculate
            </button>
        </div>
    </div>
</template>

<script>
    import {mapState} from 'vuex';
    import {mapGetters} from 'vuex';
    import {mapMutations} from 'vuex';

    export default {
        name: "StoreComponent",
        data: function () {
            return {
                productName: '',
                productPrice: 0,
            }
        },
        // computed: {
        //     count() {
        //         return this.$store.state.count;
        //     },
        //
        // },
        computed: {
            countPlusLength() {
                return this.countPlus.toString().length;
            },
            countPCountPlusCache() {
                return this.$store.getters.countCache;
            },
            countPCountPlusFunc() {
                return this.$store.getters.countFunc(2);
            },
            ...mapState({
                count: state => state.count,

                countPlus: 'countPlus',

                countLength(state) {
                    return state.countLength;
                },
                pName: 'productName',
                pPrice: 'productPrice',
                pTotal: 'productTotal',

            }),
            // 使用对象展开运算符将 getter 混入 computed 对象中
            // ...mapGetters([
            //     'countCache',
            //     'countFunc',
            // ]),


            ...mapGetters({
                // 把 `this.countCa` 映射为 `this.$store.getters.countCache`
                countCa: 'countCache',
                // 把 `this.countFu` 映射为 `this.$store.getters.countFunc`
                countFu: 'countFunc',
            }),
        },
        // computed: mapState([
        //     'count',
        //     'countPlus',
        //     'countLength',
        // ]),
        methods: {
            increment() {
                this.$store.commit('increment');
            },
            decrement() {
                this.$store.commit('decrement');
            },
            // calculate() {
            //     let payload = {
            //         price: this.productPrice,
            //         name: this.productName,
            //     };
            //     // this.$store.commit('calculate', payload);
            //
            //     // this.$store.commit({
            //     //     type: 'calculate',
            //     //     price: this.productPrice,
            //     //     name: this.productName,
            //     // });
            // },
            ...mapMutations([
                'calculate',
            ]),
        }
    }
</script>

<style scoped>

</style>

效果:

vue.test vuex mutations2

猜你喜欢

转载自www.cnblogs.com/dzkjz/p/12767970.html