zoukankan      html  css  js  c++  java
  • Vuex Action

    Action 类似于 mutation,不同在于:

    • Action 提交的是 mutation,而不是直接变更状态。
    • Action 可以包含任意异步操作

    Action 函数接受一个 context 对象【与 store 实例具有相同方法和属性】context 对象不是 store 实例本身

    你可以调用 context.commit 提交一个 mutation,

    或者通过 context.statecontext.getters 来获取 state 和 getters。

    index.js中添加:

    actions: {
        incrementAsync(context) {
            context.commit('increment');
            //context.state.count
            //context.getters.countCache
        },
    //实践中,我们会经常用到 ES2015 的 参数解构来简化代码(特别是我们需要调用 commit 很多次的时候):
        decrementAsync({commit}) {
            commit('decrement');
        },
    //实践中,我们会经常用到 ES2015 的 参数解构来简化代码(特别是我们需要调用 commit 很多次的时候):
        incrementAsyncDelay({commit}) {
            setTimeout(() => {
                commit('increment');
            }, 1000);//可以在 action 内部执行异步操作
        },
    // 用到载荷
        decrementAsyncDelay(context, payload) {
            setTimeout(() => {
                console.log(payload);
                context.commit('decrement');
            }, 1000);//可以在 action 内部执行异步操作
        },
    },
    

    分发 Action

    Action 通过 store.dispatch 方法触发:

    store.dispatch('increment')

    通过 载荷方式进行分发:

    // 以载荷形式分发
    store.dispatch('incrementAsync', {
      amount: 10
    })
    

    通过 对象方式进行分发:

    // 以对象形式分发
    store.dispatch({
      type: 'incrementAsync',
      amount: 10
    })

    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>
                <button @click="incrementAsync">Increment Async</button>
                <button @click="decrementAsync">Decrement Async</button>
                <button @click="incrementAsyncDelay">Increment Async Delay</button>
                <button @click="decrementAsyncDelay('decrement test')">Decrement Async Delay</button>
            </div>
        </div>
    </template>
    
    <script>
        import {mapState} from 'vuex';
        import {mapGetters} from 'vuex';
        import {mapMutations} from 'vuex';
        import {mapActions} 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',
                ]),
                incrementAsync() {
    //Action 通过 store.dispatch 方法触发
                    this.$store.dispatch('incrementAsync');
                },
    //mapActions 辅助函数
                ...mapActions([
                    // 'incrementAsync',
                    'decrementAsync',
                    'incrementAsyncDelay',
                    'decrementAsyncDelay',
                ]),
            }
        }
    </script>
    
    <style scoped>
    
    </style>
    
    

    效果:

    vue.test vuex action

    组合 Action

    Action 通常是异步的,那么如何知道 action 什么时候结束呢?

    更重要的是,我们如何才能组合多个 action,以处理更加复杂的异步流程?

    首先, store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise:

    类似于C#中返回的Task;

    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;
            },
        },
        actions: {
            incrementAsync(context) {
                context.commit('increment');
                //context.state.count
                //context.getters.countCache
            },
            decrementAsync({commit}) {
                commit('decrement');
            },
            async incrementAsyncDelay({commit}) {
                setTimeout(() => {
                    commit('increment');
                }, 1000);
            },
            async decrementAsyncDelay(context, payload) {
                setTimeout(() => {
                    console.log(payload);
                    context.commit('decrement');
                }, 1000);
            },
            async comboAsyncDelay({dispatch, commit}) {
                await dispatch('incrementAsyncDelay');
                commit('decrement', await setTimeout(() => {
                    console.log('another task');
                }, 1000));
            },
        },
    });
    export default store;
    
    

    主要是:

    批注 2020-04-24 204315

    添加了async标识,await异步操作。

    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>
                <button @click="incrementAsync">Increment Async</button>
                <button @click="decrementAsync">Decrement Async</button>
                <button @click="incrementAsyncDelay">Increment Async Delay</button>
                <button @click="decrementAsyncDelay('decrement test')">Decrement Async Delay</button>
                <button @click="comboAsyncDelay">Combo Async Delay</button>
            </div>
        </div>
    </template>
    
    <script>
        import {mapState} from 'vuex';
        import {mapGetters} from 'vuex';
        import {mapMutations} from 'vuex';
        import {mapActions} 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',
                ]),
                incrementAsync() {
                    this.$store.dispatch('incrementAsync').then(() => {
                        console.log('Increment Success!');
                    });
                },
    
                ...mapActions([
                    // 'incrementAsync',
                    'decrementAsync',
                    'incrementAsyncDelay',
                    'decrementAsyncDelay',
                    'comboAsyncDelay',
                ]),
            }
        }
    </script>
    
    <style scoped>
    
    </style>
    
    

    批注 2020-04-24 204508

    以及:

    批注 2020-04-24 204553
    效果:

    vue.test vuex action2

    还有一个incrementAsync测试

    批注 2020-04-24 205105

  • 相关阅读:
    c# 扩展方法奇思妙用高级篇八:Type类扩展
    Asp.Net 上传大文件专题
    波形捕捉:(2)创建捕捉设备对象
    Capturing Waveforms【译】
    波形捕捉:(1)枚举"捕捉设备"
    C# 调用sql 2000存储过程
    HTTP请求流程(一)流程简介
    Asp.Net 上传大文件专题(4)利用ajax技术显示上传进度
    c# GDI+简单绘图(四)
    波形捕捉:(5)“捕捉缓冲区”信息
  • 原文地址:https://www.cnblogs.com/dzkjz/p/12769894.html
Copyright © 2011-2022 走看看