Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 被设计用于中大型单页应用(SPA),为不同组件之间的共享状态提供了一种统一的方式。
核心概念
const store = new Vuex.Store({
state: {
count: 0
},
getters: {
doubleCount: state => state.count * 2
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment ({ commit }) {
commit('increment')
}
}
})
State(状态)
State 是存储在 Vuex 中的状态信息,是驱动应用的数据源。在 Vue 组件中访问 Vuex state 是响应式的,当 Vuex state 发生变化时,依赖这些状态的组件也会自动更新。
Getters(获取器)
Getters 允许定义一些函数,来从 Vuex Store 中获取状态。可以认为是 store 的计算属性,它可以用于简化 store 数据,让组件获取 store 中的派生状态。
Mutations(变更)
- Mutations 定义了更改 Vuex Store 中 state 的方法。每个 mutation 都有一个字符串的事件类型 (type) 和 一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。
- Vuex 中 mutations 必须是同步函数。
Actions(动作)
- Actions 类似于 mutations,不同之处在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
- Actions 接收一个与 store 实例具有相同方法和属性的 context 对象,可以通过这个 context 对象来调用 mutations 方法或者获取 state。
const mutations = {
setPosts(state, posts) {
state.posts = posts;
}
};
const actions = {
fetchPosts({ commit }) {
return fetch('https://api.example.com/posts')
.then(response => response.json())
.then(data => {
commit('setPosts', data);
});
}
};
Modules(模块)
- 由于使用单一状态树,应用的所有状态会集中到一个大对象。当应用变得非常复杂时,store 对象就可能变得相当臃肿。
- Modules 允许将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter,甚至是嵌套子模块,从而允许更好地组织代码和更高的复用性。
// user.js
export const userModule = {
state: () => ({
user: null
}),
mutations: {
setUser(state, user) {
state.user = user;
}
},
actions: {
fetchUser({ commit }) {
// 假设这里是从API获取用户信息
const user = { name: 'John Doe', id: '1' };
commit('setUser', user);
}
},
getters: {
userName(state) {
return state.user ? state.user.name : 'Guest';
}
}
};
// posts.js
export const postsModule = {
state: () => ({
posts: []
}),
mutations: {
setPosts(state, posts) {
state.posts = posts;
}
},
actions: {
fetchPosts({ commit }) {
// 假设这里是从API获取文章列表
const posts = [{ id: 1, title: 'Vuex Modules' }];
commit('setPosts', posts);
}
},
getters: {
postsCount(state) {
return state.posts.length;
}
}
};
创建和使用模块化的store
/**
* 现在我们有了两个模块:userModule和postsModule,我们可以在创建Vuex store时将它们包含进去:
*/
// index.js
import Vue from 'vue';
import Vuex from 'vuex';
import { userModule } from './user';
import { postsModule } from './posts';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
user: userModule,
posts: postsModule
}
});
使用
<template>
<div>
<p>User: {{ userName }}</p>
<p>Posts Count: {{ postsCount }}</p>
</div>
</template>
<script>
export default {
computed: {
userName() {
return this.$store.getters['user/userName'];
},
postsCount() {
return this.$store.getters['posts/postsCount'];
}
},
created() {
this.$store.dispatch('user/fetchUser');
this.$store.dispatch('posts/fetchPosts');
}
}
</script>