当前位置: 首页 > news >正文

Pinia——Vue的Store状态管理库

一、Store 是什么?

Store (如 Pinia) 是一个保存状态和业务逻辑的实体,它并不与你的组件树绑定。换句话说,它承载着全局状态。它有点像一个永远存在的组件,每个组件都可以读取和写入它。它有三个概念,state、getter 和 action,我们可以假设这些概念相当于组件中的 datacomputedmethods

二、Pinia 是什么?

Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。

三、安装+全局引入

1、安装pinia

npm install pinia

2、创建 Pinia 实例

在项目入口文件(如 main.js)中初始化并挂载 Pinia:

// main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
app.mount('#app');

注意:需确保所有 Store 的使用在 Pinia 实例挂载之后

四、定义Store-defineStore()

Store 是用 defineStore() 定义的,它的第一个参数要求是一个独一无二的名字:

import { defineStore } from 'pinia'// 返回值最好以 `use` 开头且以 `Store` 结尾。
// (比如 `useUserStore`,`useCartStore`,`useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
export const useUserStore = defineStore('user', {// 其他配置...
})

返回值(useUserStore):最好以 `use` 开头且以 `Store` 结尾

第一个参数(user):也被用作 id ,是必须传入的, Pinia 将用它来连接 store 和 devtools。

第二个参数:可【Setup函数】或【Option对象】

1、【Option 对象】——推荐使用

传入一个带有 stateactionsgetters 属性的 Option 对象

export const useCounterStore = defineStore('counter', {state: () => ({ count: 0,name: 'Eduardo'}),getters: {doubleCount: (state) => state.count * 2,},actions: {increment() {this.count++},},
})

简单理解:

state 是 store 的数据 (data)

getters 是 store 的计算属性 (computed)

actions 是方法 (methods)

优点:简单,容易使用

2、【Setup函数】

也可以传入一个函数,该函数定义了一些响应式属性和方法,并且返回一个带有我们想暴露出去的属性和方法的对象。

export const useCounterStore = defineStore('counter', () => {const count = ref(0)const name=ref("Eduardo")const doubleCount = computed(() => count.value * 2)function increment() {count.value++}return { count, doubleCount, increment }
})

在 Setup Store 中:

  • ref() 就是 state 属性
  • computed() 就是 getters
  • function() 就是 actions
  • 注意:必须在 setup store 中返回 state 的所有属性

优点:更灵活

可以在 store 内创建侦听器

可以依赖于全局提供的属性,比如路由。

任何应用层面提供的属性都可以在 store 中使用 inject() 访问,就像在组件中一样

五、基础示例

1、创建Store:

// stores/counter.jsimport { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', {state: () => {return { count: 0.name: 'Eduardo',isAdmin: true,items: [],hasChanged: true,}},// 也可以这样定义// state: () => ({ count: 0 })actions: {increment() {this.count++},},})return { count, increment }
})

2、使用Store --useCounterStore():

<script setup>import { useCounterStore } from '@/stores/counter'const counter = useCounterStore()counter.count++// 自动补全! ✨counter.$patch({ count: counter.count + 1 })// 或使用 action 代替counter.increment()//从Store解构
// `name` 和 `doubleCount` 是响应式的 ref
// 同时通过插件添加的属性也会被提取为 ref
// 并且会跳过所有的 action 或非响应式 (不是 ref 或 reactive) 的属性
const { name, doubleCount } = storeToRefs(store)
// 作为 action 的 increment 可以直接解构
const { increment } = store
</script><template><!-- 直接从 store 中访问 state --><div>Current Count: {{ counter.count }}</div>
</template>

store 是一个用 reactive 包装的对象,就像 setup 中的 props 一样,我们不能对它进行解构

六、State

state 都是你的 store 的核心。在 Pinia 中,state 被定义为一个返回初始状态的函数。

1、定义

import { defineStore } from 'pinia'const useUserStore = defineStore('user', {// 为了完整类型推理,推荐使用箭头函数state: () => {return {// 所有这些属性都将自动推断出它们的类型count: 0,name: 'Eduardo',isAdmin: true,items: [],hasChanged: true,}},
})

2、使用

<script setup>import { useUserStore } from '@/stores/counter'const store = useUserStore()//访问store.count++//重置-将state重置为初始值store.$reset()//变更多个属性store.$patch({count: store.count + 1,name: "aaa",
})//另一种变更方式store.$patch((state) => {state.items.push({ name: 'shoes', quantity: 1 })state.hasChanged = true
})
</script>

注意:

使用Setup stores中,重置需要创建自己的$reset()方法,例如

export const useCounterStore = defineStore('counter', () => {const count = ref(0)function $reset() {count.value = 0}return { count, $reset }
})

七、Getter

1、定义

Getter 完全等同于 store 的 state 的计算值。可以通过 defineStore() 中的 getters 属性来定义它们。推荐使用箭头函数,并且它将接收 state 作为第一个参数:

export const useCounterStore = defineStore('counter', {state: () => ({count: 0,}),getters: {doubleCount: (state) => state.count * 2,},
})

大多数时候,getter 仅依赖 state。不过,有时它们也可能会使用其他 getter(自行学习)

2、使用

<script setup>
import { useCounterStore } from './counterStore'
const store = useCounterStore()
</script>
<template><p>Double count is {{ store.doubleCount }}</p>
</template>

八、Action

1、定义

Action 相当于组件中的 method。它们可以通过 defineStore() 中的 actions 属性来定义

export const useCounterStore = defineStore('main', {state: () => ({count: 0,}),actions: {increment() {this.count++},randomizeCounter() {this.count = Math.round(100 * Math.random())},},
})

action 可通过 this 访问整个 store 实例

2、使用

Action 可以像函数或者通常意义上的方法一样被调用:

<script setup>const store = useCounterStore()
// 将 action 作为 store 的方法进行调用
store.randomizeCounter()</script><template><!-- 即使在模板中也可以 --><button @click="store.randomizeCounter()">Randomize</button></template>

其他用法:

访问其他store的action

订阅action—— store.$onAction()

九、配置状态持久化——persist

过这个设置,你可以指定哪些状态属性需要被保存到 localStoragesessionStorage 中,从而在页面刷新或重新加载后仍然保持这些数据。

使用方法

  1. 安装插件
npm install pinia-plugin-persistedstate
  1. 引入并使用插件: 在 Pinia 实例中添加插件:
import './assets/main.css'
import { createApp } from 'vue'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
import {createPinia} from "pinia";import App from './App.vue'
import router from './router'const store = createPinia()
store.use(piniaPluginPersistedstate);createApp(App).use(store).use(router).mount('#app')
  1. 配置 Store 的持久化路径: 在定义 store 时,通过 persist.paths 指定需要持久化的属性:
import { defineStore } from 'pinia';export const useUserStore = defineStore('user', {state: () => ({loginType: '',clientId: '',// 其他不需要持久化的状态...}),persist: {paths: ['loginType', 'clientId'], // 只保存这两个属性},
});

这样,只有 loginTypeclientId 这两个属性会被自动同步到浏览器的存储中,在页面刷新后依然可用。

高级配置

除了 paths,还可以进一步自定义持久化行为:

  • storage:选择 localStoragesessionStorage
persist: {storage: sessionStorage,paths: ['loginType', 'clientId'],}
  • serializer:自定义数据的序列化与反序列化方式。
persist: {serializer: {serialize: (value) => JSON.stringify(value),deserialize: (value) => JSON.parse(value),},paths: ['loginType', 'clientId'],}

配置选项说明

  • key: 存储数据的键名,默认为 store 的 id。
  • storage: 数据存储位置,默认为 localStorage,也可改为 sessionStorage
  • paths: 指定哪些状态路径需要持久化,如 ['token']
  • serializer: 自定义序列化和反序列化方法,支持加密等需求。
  • beforeRestoreafterRestore: 分别在恢复数据前后触发的钩子函数。

详情可见Pinia官网:Pinia | The intuitive store for Vue.js

我只是学习路上记录了一下~

相关文章:

  • 【KWDB创作者计划】_企业级多模数据库实战:用KWDB实现时序+关系数据毫秒级融合(附代码、性能优化与架构图)
  • 基于深度学习的智能交通流量监控与预测系统设计与实现
  • Spring Boot API版本控制实践指南
  • 基于深度学习的医疗诊断辅助系统设计
  • 深入详解人工智能数学基础—概率论-KL散度在变分自编码器(VAE)中的应用
  • SHCTF-REVERSE
  • 【极致版】华为云Astro轻应用抽取IoTDA影子设备参数生成表格页面全流程
  • 如何在 iPhone 上恢复已删除的联系人:简短指南
  • OkHttp源码梳理
  • 2025 FIC wp
  • 【C语言】fprintf与perror对比,两种报错提示的方法
  • 【Webpack \ Vite】多环境配置
  • Redis一些小记录
  • lstm用电量预测+网页可视化大屏
  • 矩阵系统源码搭建热门音乐功能板块开发,支持OEM
  • 【音视频】音频编码实战
  • 用 Nodemon 解决 npm run serve 频繁重启服务
  • 华为仓颉编程语言的实际用法与使用领域详解
  • 【Arxiv 2025】Single Image Iterative Subject-driven Generation and Editing
  • jss html5-node.nodeType 属性用于表示节点的类型
  • 跨海论汉|专访白馥兰:对中国农业史的兴趣,从翻译《齐民要术》开始
  • 国家税务总局:“二套转首套”可以享受贷款利息个税专项扣除
  • 加拿大温哥华发生驾车冲撞人群事件,加拿大总理发声
  • 在县中,我看到“走出去”的渴望与“留下来”的惯性
  • 白酒瓶“神似”北京第一高楼被判侵权,法院一审判赔45万并停售
  • 政治局会议:持续稳定和活跃资本市场