Vuex 的 Action学习
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
目录:
例子
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
新建一个 store.js 文件用于创建 store 实例:
// store.js
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
在组件 App.vue 中通过 store.dispatch 方法触发 Action:
// App.vue
<template>
<!-- ... -->
</template>
<script>
import store from "./store.js";
export default {
data() {
return {}
},
created:function(){
store.dispatch('increment');
console.log(store.state.count); // 1
}
}
</script>
将 store 注入到每个子组件
Vuex 通过 store 选项,提供了一种机制将状态从根组件“注入”到每一个子组件中(需调用 Vue.use(Vuex)):
// main.js
import Vue from 'vue'
import App from './App.vue'
import Vuex from 'vuex'
import store from './store.js'
Vue.use(Vuex); // 调用Vue.use(Vuex)
new Vue({
el: '#app',
store, // “注入”
render: h => h(App)
})
再在 App.vue 中通过 store.dispatch 方法触发 Action:
// App.vue
<template>
<!-- ... -->
</template>
<script>
// import store from "./store.js"; // 现在可以不用在每个 vue 组件中导入 store 实例了
export default {
data() {
return {}
},
created:function(){
this.$store.dispatch('increment');
console.log(this.$store.state.count); // 1
}
}
</script>
提交载荷(Payload)
可以向 store.dispatch**传入额外的参数**,即 Action 的 载荷(payload):
// store.js
mutations: {
increment (state, payload) {
state.count += payload.amount;
}
},
actions: {
increment (context, payload) {
context.commit('increment', payload);
}
}
// App.vue
created:function(){
this.$store.dispatch('increment ', {
amount: 10
})
console.log(this.$store.state.count); // 10
}
对象风格的提交方式
触发 Action 的另一种方式是直接使用包含 type 属性的对象:
// App.vue
store.dispatch({
type: 'increment ',
amount: 10
})
// store.js
mutations: {
increment (state, payload) {
state.count += payload.amount;
}
},
actions: {
increment (context, payload) {
context.commit('increment', payload);
}
}
结合 promise
Action 通常是异步的,我们可以通过让被触发的 action 的处理函数返回 Promise 对象,这样就可以在异步操作结束的时候执行我们想要的操作。
// store.js
mutations: {
increment (state, payLoad) {
state.count += payLoad.amount;
}
},
actions: {
increment ({ commit }, payLoad) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('increment', payLoad);
resolve();
}, 1000);
})
}
}
// App.vue
store.dispatch('increment', {
amount: 10
}).then(() => {
console.log(store.state.count); // 10
});
// 对象风格的触发方式
store.dispatch({
type: 'increment',
amount: 10
}).then(() => {
console.log(store.state.count); // 10
});