vuex store 怎么获得.vuex dispatch 回调怎么获得

& 基础教程
Vuex Actions
action 和 mutation 类似,区别在于:
action 不改变状态,只提交(commit) mutation。
action 可以包含任意异步操作。
让我们注册一个简单的 action:
const store = new Vuex.Store({
mutations: {
increment (state) {
state.count++
actions: {
increment (context) {
mit('increment')
Action 处理函数接收一个上下文对象(context object),该对象提供了跟 store 实例相同的方法/属性,因此你可以调用 <mit 提交一个 mutation,或者通过 context.state 和 context.getters 访问 state 和 getters。稍后我们会介绍 Modules,我们将看到为什么上下文对象 (context object) 不是 store 实例自身。
在实践中,我们经常用到 ES2015
来简化代码(特别是我们要多次调用 commit 的时候):
actions: {
increment ({ commit }) {
commit('increment')
分发(Dispatch) Action
使用 store.dispatch 方法触发 action。
store.dispatch('increment')
这看起来很蠢:如果我们想增加 count,为什么我们不直接调用 <mit('increment')?回想起mutation 必须是同步函数 了吗?action 可以不是同步函数。我们可以在 action 回调函数中执行 异步操作:
actions: {
incrementAsync ({ commit }) {
setTimeout(() =& {
commit('increment')
action 同样支持 payload 格式和对象风格的 dispatch:
// dispatch 传入 payload
store.dispatch('incrementAsync', {
amount: 10
// dispatch 传入一个对象
store.dispatch({
type: 'incrementAsync',
amount: 10
日常生活行为中,更实际的例子是购物车结帐,涉及调用异步 API和分发多重 mutations:
actions: {
checkout ({ commit, state }, payload) {
// 把当前购物车的商品备份起来
const savedCartItems = [...state.cart.added]
// 发送结帐请求,并愉快地清空购物车
commit(types.CHECKOUT_REQUEST)
// 购物 API 接收一个成功回调和一个失败回调
shop.buyProducts(
// 成功操作
() =& commit(types.CHECKOUT_SUCCESS),
// 失败操作
() =& commit(types.CHECKOUT_FAILURE, savedCartItems)
注意,我们执行的是一个异步操作的流程,并通过提交 action 来记录其副作用(状态变化)。
组件中分发 Action
使用 this.$store.dispatch('xxx')(需要根组件中注入 store )在组件中分发 action,使用 mapActions 工具函数,映射组件方法到调用 store.dispatch:
import { mapActions } from 'vuex'
export default {
methods: {
...mapActions([
'increment' // 映射 this.increment() 到 this.$store.dispatch('increment')
...mapActions({
add: 'increment' // map this.add() to this.$store.dispatch('increment')
组合多个 Action
Action 通常是异步的,所以我们如何知道一个 action 何时完成?更重要的是,我们如何组合多个 action 一起操作复杂的异步流程?
第一件事是知道 store.dispatch 返回『action 回调函数被触发后的返回值』,所以你可以在 action 中返回一个 Promise 对象。
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) =& {
setTimeout(() =& {
commit('someMutation')
现在你可以这么做:
store.dispatch('actionA').then(() =& {
然后在另一个 action :
actions: {
actionB ({ dispatch, commit }) {
return dispatch('actionA').then(() =& {
commit('someOtherMutation')
最后,如果我们使用 ,很快落地的 JavaScript 特性,我们可以这样组合我们的 action:
// 假定 getData() and getOtherData() 返回的是 Promise
actions: {
async actionA ({ commit }) {
commit('gotData', await getData())
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // 等待 actionA 结束
commit('gotOtherData', await getOtherData())
store.dispatch 可能会在不同模块中,触发多个 action 回调函数。在这种情况下,返回值是一个 Promise 对象,该对象在所有被触发的回调都 resolve 之后自己再 resolve。Vuex之理解Store的用法
作者:何凯
字体:[ ] 类型:转载 时间:
本篇文章主要介绍了Vuex之理解Store的用法,Store类就是存储数据和管理数据方法的仓库,实现方式是将数据和方法已对象形式传入其实例中
1.什么是Store?
说了,Vuex就是提供一个仓库,Store仓库里面放了很多对象。其中state就是数据源存放地,对应于与一般Vue对象里面的data(后面讲到的actions和mutations对应于methods)。
在使用Vuex的时候通常会创建Store实例new Vuex.store({state,getters,mutations,actions})有很多子模块的时候还会使用到modules。
总结,Store类就是存储数据和管理数据方法的仓库,实现方式是将数据和方法已对象形式传入其实例中。要注意一个应用或是项目中只能存在一个Store实例!!
2.Store源码分析
class Store{
constructor (options = {}) {
// 1.部分2个‘断言函数'判断条件
assert(Vue, `must call Vue.use(Vuex) before creating a store
instance.`) // 在Store实例化之前一定要确保Vue的存在
assert(typeof Promise !== 'undefined', `vuex requires a Promise polyfill in this browser.`)
//确保promise存在
// 2.结构赋值拿到options里面的state,plugins和strict
state = {}, //rootState
plugins = [], // 插件
strict = false //是否严格模式
} = options
// 3.Store internal state创建store内部属性
this._options = options //存储参数
this._committing = false //标识提交状态,保证修改state只能在mutation里面,不能在外部随意修改
this._actions = Object.create(null) //存储用户定义的actions
this._mutations = Object.create(null) //存储用户定义的mutations
this._wrappedGetters = Object.create(null) //存储用户定义的getters
this._runtimeModules = Object.create(null) //存储运行时的modules
this._subscribers = [] //存储所有堵mutation变化的订阅者
this._watcherVM = new Vue() //借用Vue实例的方法,$watch来观测变化
// 4.将dispatch和commit的this指向当前store实例
const store = this
const { dispatch, commit } = this
this.dispatch = function boundDispatch (type, payload) {
return dispatch.call(store, type, payload)}
mit = function boundCommit (type, payload, options) {
return commit.call(store, type, payload, options)}}
逐步分析每一个模块。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具vuex 笔记 - wbin91 - 博客园
一个简单的状态管理
单一数据源:
const sourceOfTruth = {}
const vmA = new Vue({
data: sourceOfTruth
const vmB = new Vue({
data: sourceOfTruth
每当 sourceOfTruth 发生变化, vmA 和 vmB 都会自动更新它们的视图. 子组件可以通过 this.$root.$data 访问数据. 现在我们有了单一的数据源, 但是调试会很困难. 因为无论何时数据源发生变化都会改变程序, 但是没有任何迹象表明变化发生.
store pattern
为了解决上述问题, 我们可以引入 store pattern:
var store = {
debug: true,
message: 'Hello!'
setMessageAction (newValue) {
this.debug && console.log('setMessageAction triggered with', newValue)
this.state.message = newValue
clearMessageAction () {
this.debug && console.log('clearMessageAction triggered')
this.state.message = 'action B triggered'
所有的数据改变都发生 store 内. 这种集中的状态管理模式使我们很容易记录变化发生, 如何发生.
除了单一的数据源外, 每个 vue 实例或组件也可以有其私有状态:
var vmA = new Vue({
privateState: {},
sharedState: store.state
var vmB = new Vue({
privateState: {},
sharedState: store.state
// 如果 Vuex 不是全局的, 那么确保调用 Vue.use(Vuex) 使 Vuex 生效.
const store = new Vuex.Store({
// 数据操作
mutations: {
increment (state) {
state.count++
// 触发数据变化操作
mit('increment')
console.log(store.state.count) // -& 1
store 自动注入到子组件中
通常我们通过计算属性来访问 store 中的数据, 这样就能感知到数据发生变化.
根组件的 store 属性会注入到其所有的子组件中. (通过 Vue.use(Vuex) 生效)
const Counter = {
template: `&div&{{ count }}&/div&`,
computed: {
// 子组件通过 this.$store 访问父组件的 store
return this.$store.state.count
// 父对象中的 store 自动注入到子组件
componets: {
如果 store 中有许多数据需要访问, 每个数据都需要定义一个计算属性会非常麻烦. Vuex 提供了 mapState 来简化计算属性的定义.
import { mapState } from 'vuex'
export default {
computed: mapState({
// es6 箭头函数更加简洁
count: state =& state.count,
// 字符串 'count' 等同于 `state =& state.count`
countAlias: 'count',
// 为了访问组件的 `this`, 必须使用普通的函数
// 箭头函数会绑定 `this` 到 `mapState` 的参数这个对象
countPlusLocalState (state) {
return state.count + this.localCount
如果计算属性和 store 中数据是一一对应的, 可以使用更简单的字符串数组:
computed: mapState([
// map this.count to store.state.count
es6 的扩展操作符
使用 mapState 返回一个对象, 如果组件还有私有的计算属性, 通常我们可以使用 _.extend({localComputed}, mapState(...)) 这种方式合并对象已得到最终的 computed. 使用 es6 的扩展操作符可以简化:
computed: {
localComputed(){ /* ... */},
// 通过扩展操作符扩展 computed 对象
...mapState({
通常计算属性是基于一段 store 数据的代码, 比如过滤一个列表并计数:
computed: {
doneTodoCount() {
return this.$store.state.todos.filter(todo =& todo.done).length
如果我们需要复用这段代码, 基本就是重构提取出一个函数, 但是这样还不是很理想.
Vuex 在 store 中提供了 getters:
const store = new Vuex.Store({
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
getters: {
doneTodos: state =& {
return state.todos.filter(todo =& todo.done)
doneTodosCount: (state, getters) =& {
return getters.doneTodos.length
// 通过 `store.getters` 访问
store.getters.doneTodosCount
上面的计算属性就可以改成:
computed: {
doneTodoCount() {
return this.$store.getters.doneTodoCount
mapGetters
同 state 的 mapState 类似, getters 也有 mapGetters 来简化计算属性的定义
import { mapGetters } from 'vuex'
export default {
computed: {
// mix the getters into computed with object spread operator
...mapGetters([
'doneTodosCount',
'anotherGetter',
使用对象可以自定义对应关系
mapGetters({
// map this.doneCount to store.getters.doneTodosCount
doneCount: 'doneTodosCount'
Vuex 中的 state 只能通过 mutations 来改变. mutations 很像事件, 都有一个类型和处理函数. 处理函数是真正改变 state 的地方, 并以 state 作为第一个参数.
const store = new Vuex.Store({
mutations: {
increment (state) {
// 改变 state
state.count++
就是事件一样, 我们不能直接调用处理函数, 而是要通过 <mit(type) 来触发 mutation 处理函数.
store.commit('increment')
带 playload commit
我们可以将处理函数的参数放到第二个参数 playload 中:
mutations: {
increment (state, payload) {
state.count += payload.amount
store.commit('increment', {amount: 10})
对象风格 commit
store.commit({
type: 'increment',
playload: { amount: 10 }
默认情况下, 每一次 commit 都会发送到插件 (比如: devtools) 中. 可能你会希望某些 commit 不被记录. 这时候可以传递第三个参数以设置为静默模式:
store.commit('increment', {
}, { silent: true })
// 对象风格 commit
store.commit({
type: 'increment',
}, { silent: true })
Mutations 要遵守 Vue 的响应式规则
提前初始化所有的状态值
添加新的属性到对象时, 你应该:
使用 Vue.set(obj, 'newProp', 123) 或
直接替换新的对象: state.obj = {...state.obj, newProp: 123}
使用常量为 Mutations 命名
使用常量为 Mutations 命名是各种 Flux 实现常用的模式. 将所有常量放到一个文件中, 我们能看到整个程序有什么情况数据会发生变化.
// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'
const store = new Vuex.Store({
state: { ... },
mutations: {
// es6 特性 computed property name
// 属性名称运行时确定
[SOME_MUTATION] (state) {
// mutate state
Mutations 必须是同步的
异步 mutations 调用违反了所有的状态变化必须在 store 中进行的规定. 比如:
mutations: {
someMutation (state) {
api.callAsyncMethod(() =& {
state.count++
当上例中状态变化时, someMutation 已经结束了. 这时候如果有其他状态变化的操作发生, devtools 记录下来的状态变化就是错误的.
mapMutations
我们可以通过 this.$mit('xxx') 在组件中调用 mutations, 一般我们将这些调用分装到 methods 中, 同时 Vuex 也提供了 mapMutations 函数简化 methods 定义:
import { mapMutations } from 'vuex'
export default {
methods: {
...mapMutations([
'increment' // 映射 this.increment() 到 this.$mit('increment')
...mapMutations({
add: 'increment' // map this.add() to this.$mit('increment')
异步的 mutations 使程序的状态变化难以追踪. 为了解决异步操作, Vuex 引入了 actions.
actions 跟 mutations 非常像, 它们的不同之处在于:
actions 不改变 state, 而是 commit mutations
actions 可以包含任意的异步操作
const store = new Vuex.Store({
mutations: {
increment (state) {
state.count++
actions: {
increment (context) {
context.commit('increment')
actions 接收一个 context 对象作为参数, context 可以访问 commit, getters, state, 但是它不是 store 对象.
通常, 我们会使用 es6 的参数结构语法来简化代码:
actions: {
increment({commit}) {
commit('increment')
Dispatching Actions
actions 通过 store.dispatch 来触发:
store.dispatch('increment')
dispatch 也支持 commit 中的 playload 参数以及对象风格的调用方式.
// dispatch with a payload
store.dispatch('incrementAsync', {
amount: 10
// dispatch with an object
store.dispatch({
type: 'incrementAsync',
amount: 10
mapActions
类似 mapMutations
Actions 组合
actions 通常是异步的, 我们怎么来组合多个 actions 来执行复杂的操作?
首先我们需要知道的是 store.dispatch 返回 actions 中处理函数的返回值, 因此我们可以返回一个 Promise:
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) =& {
setTimeout(() =& {
commit('someMutation')
actionB ({ dispatch, commit }) {
return dispatch('actionA').then(() =& {
commit('someOtherMutation')
使用 async/await 语法, 可以简化为:
// 假设 getData() 和 getOtherData() 返回 Promises
actions: {
async actionA ({ commit }) {
commit('gotData', await getData())
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // wait for actionA to finish
commit('gotOtherData', await getOtherData())
当我们的程序足够大时, store 也会变得非常大, 其中的 state, getters, mutations, actions 也会非常大.
因此 Vuex 允许我们将 store 分成几个 modules, 每个 modules 都有自己的 state, getters, mutations, actions 甚至它自己的 modules.
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
store.state.a // -& moduleA's state
store.state.b // -& moduleB's state
Modules 当前状态
在 modules 中, getters 和 mutations 的第一个参数都是 modules 的 state, 同样 actions 的 context.state 也是 modules 的 state, 根节点的状态可以通过 context.rootState 访问到. getters 的可以通过第三个参数访问 $rootState:
const moduleA = {
getters: {
sumWithRootCount (state, getters, rootState) {
return state.count + rootState.count
modules 的 state 放到根节点的对应的属性中, 而 actions, mutations 和 getters 没有命名空间. 所以多个 modules 可以对同一个 commit 或 dispatch 做响应. 因此必须自己通过前缀或后缀来避免命名冲突.
动态 Modules 注册
store.registerModule('myModule', {}

我要回帖

更多关于 vuex store.dispatch 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信