天天看点

vuex 中 actions 如何各个模块间,互相调用 actions、mutations、state 等信息

一、同级 actions 调用

对于同级模块下的 actions,如何互相调用呢?

实现方式:分发 action,action 通过 store.dispatch 方法触发。

二、不同模块 actions 调用

由于 Vuex 使用了单一状态树,应用的所有状态都包含在一个大对象中。那么,随着应用的不断扩展,store 会变得非常臃肿。

为了解决这个问题,Vuex 允许我们把 store 分 module(模块)。每一个模块包含各自的状态、mutation、action 和 getter。

vuex 中 modules 可以将项目的 state 进行分块,互不干扰。那么在单个 moudule 中,actions 如何调用其他模块的 actions 或者根 actions、mutations、state ?

actions 中提供如下方法:

  • rootGetters 用于获取其他模块getter;
  • rootState 用于获取其它模块state;
  • getters 用于获取当前模块getter;
  • state 用于获取当前模块state;
  • dispatch 用于调用action,当前模块和其他模块;
  • commit 用于调用mutation,当前模块和其他模块;

(一)rootGetters

const user = {
  ......
  actions: {
    async changeUser ({ rootGetters }) {
      console.log(rootGetters) // 根 getters 与其他模块 getters 下的信息
    },
  }
}
export default user
           

(二)rootState

rootState 与上述 rootGetters 同样的,获取根 state 和 其他模块 state 下的信息。

可用于:模块 B 的 actions 里,调用模块 A 的 state。

(三)getters

const user = {
  ......
  getters: {
    name: state => state.username
  },
  actions: {
    async changeUser ({ getters }) {
      console.log(getters) // 当前模块中的 getters 信息
    },
  }
}
export default user
           

(四)state

state 与上述 getters 同样的,只能获取当前模块中 state 信息。

(五)dispatch

如果同级模块的 action 调用,我们使用 dispatch 来触发;

如果在根文件下,定义一个 log 方法,通过 dipatch 去调用,则可以通过 root 参数:

const user = {
  ......
  getters: {
    name: state => state.username
  },
  actions: {
    async changeTime ({ dispatch }, time) {
      dispatch('log', { time }, { root: true })
    },
  }
}
export default user
           

根模块 index.js 文件下:

const store = new Vuex.Store({
  actions: {
    log({}, { time }) {
      console.log(time)
    }
  },
})

export default store
           

模块 B 的 actions,需要调用模块 A 的 actions 时,可以使用 root: true 实现。这里 dispatch 的第一个参数,需要传入其他模块的 actions 路径,第二个参数为传给 actions 的数据,若不传,也需要预留,第三个参数是配置选项,申明这个 actions 不是当前模块的;

(六)commit

commit 触发 mutations,从而同步更新state,如:

const user = {
  state: {
    token: '',
  },
  mutations: {
    setToken: (state, token) => {
      state.token = token
    },
  },
  actions: {
    async Login ({ commit }, userInfo) {
      const { username, password } = userInfo
      const resp = await api.login({ username, password })
      const { tokenInfo } = resp.data
      commit('setToken', tokenInfo.token)
    },
  }
}
export default user
           

如果想触发其他模块的mutation动态更新state,则需要借助参数root:

首先在根模块 index.js 文件下:

import user from './modules/user'
import home from './modules/home'
const store = new Vuex.Store({
  state: {},
  getters: {},
  mutations: {},
  actions: {},
  /* 最好能够根据功能划分模块,将业务代码写在vuex里,尽可能地将视图层(vue)和领域层(vuex)分离 */
  modules: {
    user,
    home,
  }
})
export default store
           

然后在 home.js 文件的模块下:

const home = {
  ......
  actions: {
    async changeToken ({ commit }, token) {
      commit('user/setToken', token, { root: true }) // 重点
    },
  }
}
export default home
           

总结:commit 是调用 mutations 用的,dispatch 是调用 actions 用的,state 是当前模块的 state,而 rootState 是根 state 和其他模块的 state。

继续阅读