vue——vuex的模块化module及命名空间namespaced
参考:https://vuex.vuejs.org/zh/guide/modules.html
https://blog.csdn.net/weixin_43959963/article/details/111295725
https://blog.csdn.net/weixin_43094619/article/details/120907918
我的问题:在项目中使用vuex的module,控制台报错state为null,开启命名空间后,报错:[vuex]unknown action type 'xxx',[vuex] unknown getter ‘xxx’。
原因:开启命名空间后,模块的getter、action 及 mutation 使用时需要根据模块注册的路径调整。如:dispatch('cart/calculate', 5),cart就是模块名。
一. 前言
Vuex 为了便于维护store,允许将store分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。
默认情况下,模块内部的 action 和 mutation 仍然是注册在全局命名空间的(即根节点store下)——这样使得多个模块能够对同一个 action 或 mutation 作出响应。
getter 同样也默认注册在全局命名空间,但是目前这并非出于功能上的目的(仅仅是维持现状来避免非兼容性变更)。必须注意,不要在不同的、无命名空间的模块中定义两个相同的 getter 从而导致错误。
若想要模块具有更高的封装度和复用性,可以通过添加 namespaced: true
的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
二. 实际使用
根节点 store.js:
import Vue from 'vue'; import Vuex from 'vuex'; import cart from './cart.js'; Vue.use(Vuex); export default new Vuex.Store({ modules: { cart, }, state: { token: '', }, getters: { token: (state) => { return state.token; }, }, mutations: { SET_TOKEN(state, data) { state.token = data.token; }, }, });
1. 不使用命名空间
模块 cart.js:
const cart = { // 模块内容(module assets) state: () => ({ count: 0, // 使用 -> state.count price: 0, }), getters: { // 这里的 `state` 对象是模块的局部状态 count (state) { return state.count; // 使用 -> getters.count }, price (state) { return state.price; } }, mutations: { SET_COUNT(state) { // 这里的 `state` 对象是模块的局部状态 state.count++; }, SET_PRICE(state, total) { state.price = total; }, // 使用 -> commit('SET_PRICE', 20) }, actions: { // rootState是根节点状态 calculate({ state, commit, rootState }, data) { commit('SET_COUNT'); commit('SET_PRICE', state.count * data); }, // 使用 -> dispatch('calculate', 5) }, } export default cart;
辅助函数 mapGetters
、mapActions
的使用:
... import { mapGetters, mapActions } from 'vuex'; ... computed: { ...mapGetters(['token', 'count']), }, created() { this.calculate(5); }, methods: { ...mapActions(['calculate']), }, ...
2. 使用命名空间
模块 cart.js:
const cart = { namespaced: true, // 开启命名空间 state: () => ({ //// 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响 count: 0, // 使用 -> state.count price: 0, }), getters: { count (state) { return state.count; // 使用 -> getters['cart/count'] }, price (state) { return state.price; } }, mutations: { SET_COUNT(state) { state.count++; }, SET_PRICE(state, total) { state.price = total; }, // 使用 -> commit('cart/SET_PRICE', 20) }, actions: { calculate({ state, commit, rootState }, data) { commit('SET_COUNT'); commit('SET_PRICE', state.count * data); }, // 使用 -> dispatch('cart/calculate', 5) }, } export default cart;
辅助函数 mapGetters
、mapActions
的使用:
... import { mapGetters, mapActions } from 'vuex'; ... computed: { ...mapGetters(['token'), ...mapGetters('cart', ['count']), }, created() { this.calculate(5); }, methods: { ...mapActions('cart', ['calculate']), }, ...