Pinia——Vue的Store状态管理库

一、Store 是什么?

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

二、Pinia 是什么?

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

三、安装+全局引入

1、安装pinia

npm install pinia

2、创建 Pinia 实例

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

javascript 复制代码
// 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() 定义的,它的第一个参数要求是一个独一无二的名字:

javascript 复制代码
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 对象

javascript 复制代码
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函数】

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

javascript 复制代码
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:

javascript 复制代码
// stores/counter.js
  import { 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():

javascript 复制代码
<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、定义

javascript 复制代码
import { defineStore } from 'pinia'

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

2、使用

html 复制代码
<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()方法,例如

javascript 复制代码
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 作为第一个参数:

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

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

2、使用

html 复制代码
<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 属性来定义

javascript 复制代码
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 可以像函数或者通常意义上的方法一样被调用:

html 复制代码
<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

  2. 引入并使用插件: 在 Pinia 实例中添加插件:

javascript 复制代码
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 指定需要持久化的属性:
javascript 复制代码
import { defineStore } from 'pinia';

export const useUserStore = defineStore('user', {
  state: () => ({
    loginType: '',
    clientId: '',
    // 其他不需要持久化的状态...
  }),
  persist: {
    paths: ['loginType', 'clientId'], // 只保存这两个属性
  },
});

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

高级配置

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

  • storage :选择 localStoragesessionStorage
javascript 复制代码
persist: {
  storage: sessionStorage,
    paths: ['loginType', 'clientId'],
    }
  • serializer:自定义数据的序列化与反序列化方式。
javascript 复制代码
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

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

相关推荐
萌萌哒草头将军19 分钟前
⚡⚡⚡尤雨溪宣布开发 Vite Devtools,这两个很哇塞 🚀 Vite 的插件,你一定要知道!
前端·vue.js·vite
游离状态的猫11 小时前
JavaScript性能优化实战:从瓶颈定位到极致提速
开发语言·javascript·性能优化
小彭努力中1 小时前
7.Three.js 中 CubeCamera详解与实战示例
开发语言·前端·javascript·vue.js·ecmascript
浪裡遊2 小时前
跨域问题(Cross-Origin Problem)
linux·前端·vue.js·后端·https·sprint
滿2 小时前
Vue3 Element Plus el-tabs数据刷新方法
javascript·vue.js·elementui
LinDaiuuj2 小时前
判断符号??,?. ,! ,!! ,|| ,&&,?: 意思以及举例
开发语言·前端·javascript
Aphasia3112 小时前
react必备JavaScript知识点(二)——类
前端·javascript
玖玖passion2 小时前
数组转树:数据结构中的经典问题
前端
呼Lu噜2 小时前
WPF-遵循MVVM框架创建图表的显示【保姆级】
前端·后端·wpf