Vuex 是一个专为 Vue.js 应用设计的状态管理库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。本文将详细介绍 Vuex 的核心概念和使用方法,并通过一个完整的示例演示如何在 Vue.js 项目中集成和使用 Vuex。
在大型 Vue.js 应用中,多个组件之间可能需要共享状态。通过父子组件的 props 和事件传递数据在某些情况下会显得复杂且难以维护。Vuex 通过集中式状态管理提供了一种更好的解决方案,使得组件之间的状态共享和管理更加容易。
Vuex 包含五个核心部分:State, Getters, Mutations, Actions, 和 Modules。
首先,在 Vue 项目中安装 Vuex:
npm install vuex --save
然后,在项目中引入 Vuex:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
接下来,我们创建一个简单的 Vuex store。假设我们正在开发一个计数器应用。
// store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
count: 0
},
getters: {
doubleCount: state => state.count * 2
},
mutations: {
increment(state) {
state.count++;
},
decrement(state) {
state.count--;
}
},
actions: {
incrementAsync({ commit }) {
setTimeout(() => {
commit('increment');
}, 1000);
},
decrementAsync({ commit }) {
setTimeout(() => {
commit('decrement');
}, 1000);
}
}
});
export default store;
在这个 store 中,我们定义了:
state
:存储一个计数器的值 count
。getters
:定义一个 doubleCount
getter,它返回 count
的两倍。mutations
:定义 increment
和 decrement
两个同步函数,用于更改 count
的值。actions
:定义 incrementAsync
和 decrementAsync
两个异步函数,分别在 1 秒后调用相应的 mutation。现在我们创建一个 Vue 组件来使用这个 store。
{{ count }}
{{ doubleCount }}
在这个组件中:
mapState
将 state
中的 count
映射到组件的计算属性。mapGetters
将 getters
中的 doubleCount
映射到组件的计算属性。mapMutations
将 mutations
中的 increment
和 decrement
映射到组件的方法。mapActions
将 actions
中的 incrementAsync
和 decrementAsync
映射到组件的方法。对于大型应用,可以将 store 拆分为模块,每个模块拥有自己的 state、getters、mutations 和 actions。
// store/modules/counter.js
const state = {
count: 0
};
const getters = {
doubleCount: state => state.count * 2
};
const mutations = {
increment(state) {
state.count++;
},
decrement(state) {
state.count--;
}
};
const actions = {
incrementAsync({ commit }) {
setTimeout(() => {
commit('increment');
}, 1000);
},
decrementAsync({ commit }) {
setTimeout(() => {
commit('decrement');
}, 1000);
}
};
export default {
namespaced: true,
state,
getters,
mutations,
actions
};
然后在主 store 文件中引入这个模块:
// store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import counter from './modules/counter';
Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
counter
}
});
export default store;
使用模块化的 store 后,在组件中访问和使用模块化的状态和方法:
{{ count }}
{{ doubleCount }}
接下来,我们演示一个更复杂的场景:用户登录。这个示例将展示如何通过 Vuex 和 API 调用进行用户认证。
首先,定义一个用于登录的 API 调用函数:
// api/login.js
import axios from 'axios';
export function login(username, password, code, uuid) {
const data = {
username,
password,
code,
uuid
};
return axios({
url: '/login',
method: 'post',
data
});
}
接下来,在 Vuex 中定义登录逻辑:
// store/modules/user.js
import { login } from '@/api/login';
const state = {
token: '',
userInfo: {}
};
const getters = {
isLoggedIn: state => !!state.token
};
const mutations = {
SET_TOKEN(state, token) {
state.token = token;
},
SET_USER_INFO(state, userInfo) {
state.userInfo = userInfo;
},
LOGOUT(state) {
state.token = '';
state.userInfo = {};
}
};
const actions = {
async login({ commit }, loginForm) {
try {
const response = await login(
loginForm.username,
loginForm.password,
loginForm.code,
loginForm.uuid
);
const { token, userInfo } = response.data;
commit('SET_TOKEN', token);
commit('SET_USER_INFO', userInfo);
} catch (error) {
throw new Error('Login failed');
}
},
logout({ commit }) {
commit('LOGOUT');
}
};
export default {
namespaced: true,
state,
getters,
mutations,
actions
};
// store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import user from './modules/user';
Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
user
}
});
export default store;
最后,创建一个登录组件,使用 Vuex 进行状态管理:
Login
在这个组件中:
loginForm
用于绑定表单数据,包括用户名、密码和验证码。captchaSrc
用于存储验证码图片的 URL。mapActions
将 user
模块中的 login
action 映射到组件的方法。handleLogin
方法调用 Vuex 的 login
action 进行登录,并根据结果进行路由跳转或显示错误信息。getCaptcha
方法获取新的验证码。主要过程:
mapState
、mapGetters
、mapMutations
和 mapActions
将 Vuex 的状态和方法映射到 Vue 组件。使用 Vuex 的好处: