1. 程式人生 > >vuex 2.0學習心得(中) mutation&action

vuex 2.0學習心得(中) mutation&action

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">

           <[email protected]="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">

           <[email protected]="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">

           <[email protected]="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)

        }

    }

})