store
是一个全局状态管理器,用于在整个 Vue 应用中管理和共享状态。通过使用 store
,你可以避免组件之间直接传递数据,从而使得状态管理更加集中和可维护。
在 Vue 3 中,Pinia 和 Vuex 都是常用的状态管理库。Pinia 是 Vue 3 官方推荐的状态管理库,具有更简洁的 API 和更好的类型支持。
为什么需要全局状态管理器?
在复杂的应用中,组件之间的通信和状态共享可能变得复杂和难以维护。全局状态管理器提供了一种集中管理应用状态的方法,使得状态的变化和共享变得更加清晰和可控。
全局状态管理器的主要功能
- 集中管理状态:将应用的所有状态集中在一个地方,便于管理和调试。
- 组件间共享状态:不同组件可以方便地访问和修改全局状态,而不需要通过父子组件传递数据。
- 持久化状态:可以将状态持久化到本地存储中,以便在页面刷新或重启时保持状态。
- 调试和时间旅行:通过插件和工具,可以方便地调试状态的变化,甚至进行时间旅行(回溯状态变化)。
使用 Pinia 作为全局状态管理器
接下来,我们以 Pinia 为例,展示如何在 Vue 3 中使用全局状态管理器。
1. 安装 Pinia
npm install pinia
2. 创建一个 Pinia Store
// src/store/auth.js
import { defineStore } from 'pinia';
import axios from 'axios';
export const useAuthStore = defineStore('auth', {
state: () => ({
loggedIn: localStorage.getItem('loggedIn') === 'true',
username: localStorage.getItem('username') || '',
}),
actions: {
setLoggedIn(status) {
this.loggedIn = status;
if (status) {
localStorage.setItem('loggedIn', 'true');
} else {
localStorage.removeItem('loggedIn');
localStorage.removeItem('username');
}
},
setUsername(username) {
this.username = username;
localStorage.setItem('username', username);
},
async register(username, password) {
try {
const response = await axios.post('/api/register', { username, password });
if (response.status === 201) {
this.setUsername(username);
this.setLoggedIn(true);
} else {
console.error('注册失败:', response.data.message);
}
} catch (error) {
console.error('注册时发生错误:', error);
}
},
async login(username, password) {
try {
const response = await axios.post('/api/login', { username, password });
if (response.status === 200) {
this.setUsername(username);
this.setLoggedIn(true);
} else {
console.error('登录失败:', response.data.message);
}
} catch (error) {
console.error('登录时发生错误:', error);
}
},
logout() {
this.setLoggedIn(false);
this.setUsername('');
},
},
});
3. 在 Vue 应用中使用 Pinia
// src/main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import router from './router';
const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
app.use(router);
app.mount('#app');
4. 在组件中使用 Pinia Store
登录组件示例:
<!-- src/components/Login.vue -->
<template>
<div class="login-container">
<h1>登录</h1>
<form @submit.prevent="handleLogin">
<div class="form-group">
<label for="username">用户名</label>
<input type="text" id="username" v-model="username" required />
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" id="password" v-model="password" required />
</div>
<button type="submit">登录</button>
</form>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { useAuthStore } from '../store/auth';
const username = ref('');
const password = ref('');
const authStore = useAuthStore();
const router = useRouter();
const handleLogin = async () => {
await authStore.login(username.value, password.value);
if (authStore.loggedIn) {
router.push('/');
}
};
</script>
<style scoped>
.login-container {
max-width: 400px;
margin: 0 auto;
padding: 20px;
border: 1px solid #ccc;
border-radius: 4px;
background-color: #fff;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
}
.form-group input {
width: 100%;
padding: 8px;
box-sizing: border-box;
}
button {
width: 100%;
padding: 10px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
注册组件示例:
<!-- src/components/Register.vue -->
<template>
<div class="register-container">
<h1>注册</h1>
<form @submit.prevent="handleRegister">
<div class="form-group">
<label for="username">用户名</label>
<input type="text" id="username" v-model="username" required />
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" id="password" v-model="password" required />
</div>
<button type="submit">注册</button>
</form>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { useAuthStore } from '../store/auth';
const username = ref('');
const password = ref('');
const authStore = useAuthStore();
const router = useRouter();
const handleRegister = async () => {
await authStore.register(username.value, password.value);
if (authStore.loggedIn) {
router.push('/');
}
};
</script>
<style scoped>
.register-container {
max-width: 400px;
margin: 0 auto;
padding: 20px;
border: 1px solid #ccc;
border-radius: 4px;
background-color: #fff;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
}
.form-group input {
width: 100%;
padding: 8px;
box-sizing: border-box;
}
button {
width: 100%;
padding: 10px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
总结
- 全局状态管理器:用于在整个应用中管理和共享状态,避免组件之间直接传递数据。
- Pinia:Vue 3 官方推荐的状态管理库,具有简洁的 API 和良好的类型支持。
-
安装 Pinia:通过
npm install pinia
安装。 -
创建 Store:使用
defineStore
定义store
,包括状态、动作和 getters。 - 在应用中使用 Pinia:在应用的入口文件中引入并使用 Pinia。
-
在组件中使用 Store:通过
useAuthStore
钩子访问和操作store
。
通过使用全局状态管理器,你可以更好地管理 Vue 应用中的状态,使得代码更加简洁和可维护。