在 Vue 2 中使用 Vuex 进行状态管理时,如果你的应用变得复杂,可以将 Vuex store 分割成多个模块(module)。每个模块拥有自己的 state、mutations、actions、getters 等,使得状态管理更加清晰和模块化。
以下是一个基于 Vue 2 和 Vuex 的模块化示例:
1. 创建 Vuex Store 并定义模块
首先,在 src/store 目录下创建一个 index.js 文件,并在其中定义 Vuex store,同时引入你将要创建的模块。
// src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import authModule from './modules/auth'; // 引入认证模块
import userModule from './modules/user'; // 引入用户模块
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
auth: authModule, // 注册认证模块
user: userModule // 注册用户模块
}
});
接着,在 src/store/modules 目录下创建 auth.js 和 user.js 文件,分别定义认证模块和用户模块。
认证模块(auth.js)
// src/store/modules/auth.js
const authModule = {
namespaced: true, // 启用命名空间
state: {
isLoggedIn: false,
user: null
},
mutations: {
setUser(state, user) {
state.user = user;
state.isLoggedIn = !!user;
},
logout(state) {
state.user = null;
state.isLoggedIn = false;
}
},
actions: {
login({ commit }, user) {
// 模拟登录逻辑
setTimeout(() => {
commit('setUser', user);
}, 1000);
},
logout({ commit }) {
commit('logout');
}
},
getters: {
isLoggedIn: state => state.isLoggedIn,
currentUser: state => state.user
}
};
export default authModule;
用户模块(user.js)
// src/store/modules/user.js
import profileModule from './profile'; // 引入用户资料子模块
const userModule = {
namespaced: true, // 启用命名空间
modules: {
profile: profileModule // 注册用户资料子模块
},
state: {
username: ''
},
mutations: {
setUsername(state, username) {
state.username = username;
}
},
actions: {
updateUsername({ commit }, username) {
commit('setUsername', username);
}
},
getters: {
username: state => state.username
}
};
export default userModule;
同时,你可以在 src/store/modules 目录下创建 profile.js 文件,定义用户资料子模块。
// src/store/modules/profile.js
const profileModule = {
state: {
bio: ''
},
mutations: {
setBio(state, bio) {
state.bio = bio;
}
},
actions: {
updateBio({ commit }, bio) {
commit('setBio', bio);
}
},
getters: {
bio: state => state.bio
}
};
export default profileModule;
2. 在主应用中引入 Store
这一步与前面的非模块化示例相同,只需确保在 main.js 中引入了 store/index.js 定义的 store。
// src/main.js
import Vue from 'vue';
import App from './App.vue';
import store from './store';
new Vue({
store,
render: h => h(App)
}).$mount('#app');
3. 在组件中使用模块化 Store
由于启用了命名空间,你需要在组件中通过指定模块名来访问状态、提交 mutation 或分发 action。
<template>
<div>
<p>Username: {{ username }}</p>
<p>Bio: {{ bio }}</p>
<p v-if="isLoggedIn">Logged in as: {{ currentUser.username }}</p>
<button @click="updateUsername('newUsername')">Update Username</button>
<button @click="updateBio('New bio description')">Update Bio</button>
<button @click="login">Login</button>
<button @click="logout" v-if="isLoggedIn">Logout</button>
</div>
</template>
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
export default {
computed: {
...mapState({
// 从根 state 映射状态(如果有的话)
}),
...mapState('user', { // 从 user 模块映射状态
username: state => state.username
}),
...mapGetters('user/profile', { // 从 user/profile 模块映射 getter
bio: 'bio'
}),
...mapGetters('auth', { // 从 auth 模块映射 getter
isLoggedIn: 'isLoggedIn',
currentUser: 'currentUser'
})
},
methods: {
...mapActions('user', ['updateUsername']), // 从 user 模块映射 action
...mapActions('user/profile', ['updateBio']), // 从 user/profile 模块映射 action
...mapActions('auth', ['login', 'logout']) // 从 auth 模块映射 action
// 你也可以直接调用 action,但需要使用完整的命名空间路径
// login() {
// this.$store.dispatch('auth/login', { username: 'admin', password: 'password' });
// }
}
};
</script>
在这个组件中,我们使用了 mapState、mapGetters 和 mapActions 辅助函数来映射用户模块和用户资料子模块的状态、getter 和 action,以及认证模块的状态和 action。注意,在映射时,我们需要指定模块名(如 user、user/profile、auth)来访问相应的状态、getter 和 action。
通过这种方式,你可以将 Vuex store 分割成多个模块,使得状态管理更加清晰和模块化。每个模块都可以有自己的状态、mutations、actions 和 getters,同时可以通过命名空间来避免命名冲突。




Comments NOTHING