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:
})
這個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。所謂的型別型其實指的就是函式的名稱。
Action去comit一個mutation。它要指定去commit哪一個mutation,然後指定結束之後要做什麼什麼事情就要給出一個函式,所以說mutation的構成有兩點名稱和函式。
const store = new Vuex.Store({
state: {
count:0
},
mutations: {
increment(state) {
state.count++;
},
decrement(state) {
state.count--
}
}
})
Action
action去commitmutations,所以還要定義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提供一個物件,物件的屬性是事件處理函式名字,屬性值是對應的dispatch的action的名字。
<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>
同樣,actions和mutations 中的處理函式也是一樣,它除了可以得到預設引數外,還可以接受自定義的引數,我們自定義的引數,依次在預設引數後面列出來就可以了。 在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)
}
}
})