Vuex (vue2.0) 基础mutation&action(理解)

Vuex采用和Redux类似的单向数据流的方式来管理数据。用户界面负责触发动作(Action)进而改变对应状态(State),从而反映到视图(View)上。如下图所示:

 

完整的Vuex用Vuex开发的应用结构应该是这样的:

devtools          工具        

 

backbend API      后台数据接口

 

actions           动作定义方法

 

dispatch          处理

mutations         变化 响应

state             状态

 

store             仓库

 

State

State负责存储整个应用的状态数据,一般需要在使用的时候在跟节点注入store对象,后期就可以使用this.$store.state直接获取状态

//store为实例化生成的

import storefrom'./store'

 

new Vue({

  el: '#app',

  store,

  render: h => h(App)

})

这个store可以理解为一个容器,包含着应用中的state等。实例化生成store的过程是:

const mutations = {...};
const actions = {...};
const state = {...};
 
Vuex.Store({
  state,
  actions,
  mutation
});

后续在组件中使用的过程中,如果想要获取对应的状态你就可以直接使用this.$store.state获取,当然,也可以利用vuex提供的mapState辅助函数将state映射到计算属性中去,如.

//我是组件
import {mapState} from 'vuex'
export default {
  computed: mapState({
count: state => state.count
  })
}

这样直接就可以在组件中可以获取store。中的state数据,用于初始化信息等信息的存放。

Mutations

Mutations中文意思是变化响应, The only way to actually change state in a Vuex store is bycommitting a mutation,vue中,只有mutation才能正真改变VUEX stroe中的state.  mutation类似事件,每一个mutation都有一个类型和一个处理函数,因为只有mutation才能改变state.所以处理函数都会自动获取一个默认的参数名称-state。所谓的类型型其实指的就是函数的名称。

Actioncomit一个mutation。它要指定去commit哪一个mutation,然后指定结束之后要做什么什么事情就要给出一个函数,所以说mutation的构成有两点名称和函数。

 

 

const store = new Vuex.Store({
    state: {
        count:0
    },
mutations: {
        increment(state) {
            state.count++;
        },
        decrement(state) {
            state.count--
        }
    }
})


Vuex 建议我们类型使用大写

Action

actioncommitmutations,所以还要定义action. store.js里面添加actions.

    actions: {
        increment(context) {
            context.commit("INCREMENT");
        },
        decrement(context) {
            context.commit("DECREMENT");
        }
    }

Action其实和mutation 是一样的,同样的结构,类型和函数。原因是我们在后面要dispatch一个action,所以action需要一个名字让我们找到,然后找到后执行的方法。

函数会自动获得一个默认参数context, 它是一个store实例,通过它可以获取到store实例的属性和方法,context.state就会获取到 state属性, context.commit就会执行commit命令。

Context 相当与一个store对象的实例(也是对象),我们可以通过对象的解构赋值直接获取到该方法。

修改后的actions如下:

actions: {
        increment({commit}){
            commit("INCREMENT")
        },
        decrement({commit}){
            commit("DECREMENT")
        }
    }

+

dispatch  action

  在就剩下dispatch action了。什么时候dispatch action呢?只有当我们点击按钮的时候.给按钮添加click事件,click事件处理函数的中dispatch action.

 打开increment.vue组件,给两个按钮添加click事件。

<template>
    <div>
        <button @click="increment">+1</button>
        <button @click="decrement">-1</button>
    </div>
</template>
 
<script>
    export default {
        methods: {
            increment(){
                this.$store.dispatch("increment");
            },
            decrement() {
                this.$store.dispatch("decrement")
            }
        }
    }
</script>

其实像上面dispatchaction比较麻烦,如果有10个按钮,我们要写10个函数,且存在大量的重复,并且我们的事件处理函数名字和action的名字是一样的

这种组件中的事件处理函数名字和action的名字是相同的,直接把事件处理函数名字放到一个数组中。组件中的methods修改如下:

   import {mapActions} from "vuex";

   export default {

       methods: {

           ...mapActions(["increment", "decrement"])

       }

    }

 

如果事件处理函数名字和action的名字不同,给mapActions提供一个对象,对象的属性是事件处理函数名字,属性值是对应的dispatchaction的名字。

<template>

   <div>

       <button @click="add">+1</button>    <!-- 事件处理函数变为add -->

       <button @click="decrement">-1</button>

   </div>

</template>

 

<script>

   import {mapActions} from "vuex";

   export default {

       methods: {

           ...mapActions(["decrement"]),

       // mapActions 对应做出改变

           ...mapActions({

                add: "increment"

           })

       }

    }

通过vuex 传递参数

很多时候,组件和组件之间还要传递参数,这些都要经过vuex increment组件内部增加一个输入框和一个按钮,点击按钮的时候,count增加输入框内的值。

<template>

   <div>

       <div>

           <button @click="increment">+1</button>

           <button @click="decrement">-1</button>

       </div>
    // 增加内容

        <div>

           <input type="text" v-model="incrementValue">

           <button@click="incrementWithValue">increment</button>

       </div>

   </div>

</template>

在组件内部dipatch action 的时候,他可以自定义参数,只要参数在他dispatch 的action 后面,一次排列出来就可以了。在这里,我们点击按钮的时候,触发一个incrementWithValue action ,打一个参数就可以这样写this.$store.dispatch(“increamentValue”,value)increament.vue组件如下:

<template>

   <div>

       <div>

           <button @click="increment">+1</button>

           <button @click="decrement">-1</button>

       </div>

       <div>

           <input type="text" v-model="incrementValue">

           <button@click="incrementWithValue">increment</button>

       </div>

   </div>

</template>

 

<script>

    import{mapActions} from "vuex";

   export default {

       data() {

           return {

                incrementValue: 0

           }

       },

       methods: {

           ...mapActions(["increment","decrement"]),

           incrementWithValue() {

                //调用store中定义的方法,store,index.js的action方法作者也是定义成了incrementWithValue

                this.$store.dispatch("incrementWithValue",this.incrementValue)

           }

       }

    }

</script>

  同样,actionsmutations 中的处理函数也是一样,它除了可以得到默认参数外,还可以接受自定义的参数,我们自定义的参数,依次在默认参数后面列出来就可以了。 store.js中分加增加incrementWithValueaction INCREMENT_WITH_VALUE mutation 

conststore = new Vuex.Store({

    state: {

        count:0

    },

    mutations: {

        //加1

        INCREMENT(state) {

            state.count++;

        },

        //减1

        DECREMENT(state) {

            state.count--

        },

        INCREMENT_WITH_VALUE(state, value){

            state.count +=value;

        }

    },

    actions: {

        increment({commit}){

            commit("INCREMENT")

        },

        decrement({commit}){

            commit("DECREMENT")

        },

        incrementWithValue({commit}, value){

            commit("INCREMENT_WITH_VALUE",  parseInt(value))

        }

    }

})

错误处理

当我们给vuex传参的时候,我们要检测参数的正确性,如果有错误需要进行处理

action 中如果是同步操作,就用try..catch语句,组件中使用try…catch,捕获action中抛出的错误。Increment.vue组件中,incrementWithValue()方法中修改如下:

methods: {

           ...mapActions(["increment","decrement"]),

            incrementWithValue() {

                 try {

                     this.$store.dispatch("incrementWithValue",this.incrementValue)

                 }catch(error) {

                     alert(error)

                 }

            }

        }

 同时store.js中的action 也进行如下修改:

incrementWithValue({commit},value){

    let intValue = parseInt(value);

    if(isNaN(intValue)){

        throw "Not an Interger"

    }else {

       commit("INCREMENT_WITH_VALUE", intValue)

    }

}

 如果action中进行的是异步操作,那就需要在回调函数中进行错误处理。

incrementWithValue({commit},value){

      let intValue = parseInt(value)

            setTimeout(function() {

 

                if(isNaN(intValue)) {

                    alert("Not anInterger")

                }else {    

                   commit("INCREMENT_WITH_VALUE", intValue)

                }

            }, 2000)

        }

异步操作给出用户提示信息

首先,在我们的increment.vue中添加一个提示信息,简单给一个div进行提示。用户提示信息的显示和隐藏,又涉及到一个状态,我们设为waiting,需要在state 中进行添加。默认为false, 同时我们组件需要从state 中获取到初始状态。increment.vue组件修改如下:

<template>

   <div>

       <div>

           <button @click="increment">+1</button>

           <button @click="decrement">-1</button>

       </div>

       <div>

           <input type="text" v-model="incrementValue">

           <button@click="incrementWithValue">increment</button>

       </div>

       <!-- 展示信息 -->

       <div v-if ="show">

           waiting

       </div>

   </div>

</template>

 

<script>

   import {mapActions} from "vuex";

   export default {

       data() {

           return {

                incrementValue: 0

           }

       },
    // computed 从state 中获取初始状态

       computed: {

           show: function() {

                return this.$store.state.waiting;

           }

       },

       methods: {

           ...mapActions(["increment","decrement"]),

           incrementWithValue() {

                this.$store.dispatch("incrementWithValue",this.incrementValue)

           }

       }

    }

</script>

mutation 去操作状态,所以增加两个muatation, 用于显示和隐藏waiting. action 中去触发这两个mutation. 整个state 如下:

conststore = new Vuex.Store({

    state: {

        count:0,

        //新增waiting  状态

        waiting: false

    },

    mutations: {

        //加1

        INCREMENT(state) {

            state.count++;

        },

        //减1

        DECREMENT(state) {

            state.count--

        },

        INCREMENT_WITH_VALUE(state, value){

            state.count +=value;

       },

        //显示和隐藏waiting

        SHOW_WAITING_MESSAGE(state){

            state.waiting = true;

        },

        HIDE_WAITING_MESSAGE(state){

            state.waiting = false;

        }

    },

    actions: {

        increment({commit}){

            commit("INCREMENT")

        },

        decrement({commit}){

            commit("DECREMENT")

        },

        incrementWithValue({commit}, value){

           commit("SHOW_WAITING_MESSAGE");

            let intValue = parseInt(value)

            setTimeout(function() {

                if(isNaN(intValue)) {

                    alert("Not anInterger")

                }else {   

                   commit("HIDE_WAITING_MESSAGE");

                   commit("INCREMENT_WITH_VALUE", intValue)

                }

            }, 2000)

        }

    }

})


Logo

前往低代码交流专区

更多推荐