跳到主要内容

4.2 Pinia 与共享状态

本章目标: 用 store 共享多个页面需要的状态,避免把所有状态都塞进全局。

先判断是否需要共享​

状态通常放在哪里
表单输入、弹窗是否显示当前组件
一块业务区域的请求状态组合式函数或页面
页面可分享的筛选条件URL query
当前用户、跨页面偏好Pinia
数据库里的真实任务服务端,前端只是缓存

Pinia 是 Vue 官方推荐的状态管理库。它不能代替数据库,也不会自动把内存状态持久化到浏览器。

安装与注册​

npm install pinia

在 main.ts 现有应用上注册:

src/main.ts(接续 Router 章节)
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import { router } from './router';

createApp(App).use(createPinia()).use(router).mount('#app');

声明 Setup Store​

src/stores/preferences.ts
import { computed, ref } from 'vue';
import { defineStore } from 'pinia';

export const usePreferencesStore = defineStore('preferences', () => {
const hideCompleted = ref(false);
const description = computed(() => hideCompleted.value ? '仅显示未完成' : '显示全部');

function toggleVisibility() {
hideCompleted.value = !hideCompleted.value;
}

return { hideCompleted, description, toggleVisibility };
});

store ID 在应用里应唯一。ref 类似 state,computed 类似 getter,函数类似 action。Setup Store 的状态应返回给 Pinia 管理,不要把需要管理的状态藏在闭包里。

组件里使用​

可放入任一已注册 Pinia 的页面
<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { usePreferencesStore } from '../stores/preferences';

const preferences = usePreferencesStore();
const { hideCompleted, description } = storeToRefs(preferences);
</script>

<template>
<section>
<label><input v-model="hideCompleted" type="checkbox" /> 隐藏已完成</label>
<p>{{ description }}</p>
<button type="button" @click="preferences.toggleVisibility">切换</button>
</section>
</template>

从 src/views 导入用 ../stores/preferences,从 App.vue 导入则用 ./stores/preferences。

不要直接解构 state

const { hideCompleted } = preferences 会得到读取时的值。使用 storeToRefs 提取 state/getter,方法可以直接使用或解构。

生命周期与持久化​

同一个 Pinia 实例中,调用同一个 store 会得到共享状态。刷新页面通常会重新初始化。需要保存偏好时,可以明确读写 localStorage,或采用合适的持久化插件。

localStorage 内容可能缺失、过期或被修改,读取时要验证。密码、后端密钥不能放在前端 store。认证方案另见登录与权限。

SSR 应为每个请求创建正确的应用和 Pinia 实例,避免模块级共享用户数据。

练习​

在列表页和 about 页都显示 description,在一个页面切换后跳转另一个页面,确认偏好仍然一致。刷新后观察状态变化。

检查答案

页面跳转不销毁整个 Pinia 实例,所以状态保留。刷新重新创建应用,未加持久化时状态回到初始值是预期行为。

参考:Pinia 简介、Store 核心概念。