Vue3状态管理Pinia

1、Pinia介绍

Pinia 是 Vue 官方推荐的状态管理库,由 Vuex 团队核心成员开发,用于替代 Vuex(Vue 3 已将 Pinia 作为官方状态管理方案)。它专为 Vue 2 和 Vue 3 设计,API 简洁直观,且原生支持 TypeScript,是处理跨组件/页面共享状态的最佳选择。

Pinia 的核心特点

  1. 简化的 API:移除了 Vuex 中的 mutations(仅保留 stategettersactions),减少模板代码。
  2. TypeScript 友好:天生支持类型推断,无需手动定义类型。
  3. 多 Store 支持:可以创建多个独立的 store,避免单一状态树的臃肿。
  4. 响应式集成:状态自动具备响应式,直接在组件中使用即可触发更新。
  5. 异步支持actions 可直接处理异步逻辑(无需像 Vuex 那样区分 actionsmutations)。
  6. 代码分割:自动拆分打包,仅加载用到的 store。

Pinia 核心概念

Pinia 的这几个核心概念是状态管理的基础,我们可以结合 Vue 组件的特性来类比理解,让概念更直观:

1. Store(状态容器)

  • 定义:Store 是 Pinia 中最核心的概念,本质是一个「状态容器」,用于集中管理应用中需要跨组件共享的数据(比如用户信息、购物车数据等)。
  • 特点
    • 每个 Store 必须通过 defineStore 函数定义,且需要一个唯一的 ID(字符串),这个 ID 是 Pinia 区分不同 Store 的标识(类似组件的 name 属性)。
    • 一个应用可以有多个 Store,按业务模块拆分(比如 userStore 管理用户状态、cartStore 管理购物车),避免像 Vuex 那样所有状态挤在一个「单一状态树」里。
  • 类比:可以理解为一个「全局的组件」,但它不负责渲染 UI,只负责管理数据和逻辑。

2. State(状态数据)

  • 定义:State 是 Store 中存储原始数据的地方,相当于组件中的 data 选项。
  • 特点
    • 是响应式的:当 State 中的数据发生变化时,所有使用该数据的组件会自动更新(和 Vue 组件的响应式原理一致)。
    • 定义方式:通过函数返回一个对象(避免在服务端渲染时出现状态污染),例如 state: () => ({ count: 0, user: null })
  • 作用:保存应用的「源数据」,是整个状态管理的「数据源」。
  • 类比:就像组件里的 data() 返回的对象,只不过这些数据可以被整个应用的任何组件访问和修改。

3. Getters(派生状态)

  • 定义:Getters 用于基于 State 计算派生状态,相当于组件中的 computed 计算属性。
  • 特点
    • 缓存机制:Getters 的返回值会被缓存,只有当它依赖的 State 发生变化时,才会重新计算(和 computed 一样,提高性能)。
    • 支持依赖其他 Getters:可以在一个 Getters 中调用另一个 Getters(通过第二个参数 getters 访问)。
    • 可以传参:通过返回一个函数实现,例如 getters: { getUserById: (state) => (id) => state.users.find(u => u.id === id) }
  • 作用:对 State 进行加工处理,得到新的状态(比如从列表中筛选数据、计算总和等)。
  • 类比:类似组件中 computed,从现有数据中「计算」出新数据,且自动追踪依赖。

4. Actions(状态修改逻辑)

  • 定义:Actions 是 Store 中定义方法的地方,用于修改 State 或处理业务逻辑,相当于组件中的 methods
  • 特点
    • 支持同步和异步:可以直接写异步逻辑(比如调用 API、定时器等),无需像 Vuex 那样区分 actions(异步)和 mutations(同步)。
    • 直接修改 State:在 Actions 中可以通过 this 直接访问和修改 State(例如 this.count++)。
    • 可复用逻辑:多个组件可以调用同一个 Action,实现逻辑复用。
    • 可以调用其他 Actions:通过 this 访问当前 Store 的其他 Actions(this.otherAction())。
  • 作用:封装修改状态的逻辑(避免在组件中直接修改 State 导致逻辑分散),尤其是复杂逻辑或异步操作。
  • 类比:类似组件中的 methods,但它的操作对象是全局的 State,而不是组件内部的 data

总结关系

  • Store 是容器,包含了 State(数据)、Getters(计算数据)、Actions(操作数据的方法)。
  • 组件通过调用 Store 的 Actions 修改 State,通过访问 State 或 Getters 获取数据,从而实现跨组件的状态共享和联动。

使用示例

下面通过两个场景演示 Pinia 的用法:基础计数器、异步获取用户信息。

1. 安装 Pinia
# Vue 3 项目
npm install pinia
# 或
yarn add pinia
2. 初始化 Pinia

在入口文件(如 main.js)中创建 Pinia 实例并挂载到 Vue 应用:

// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)
const pinia = createPinia() // 创建 Pinia 实例

app.use(pinia) // 挂载到应用
app.mount('#app')
3. 示例 1:基础计数器 Store

创建一个管理计数器状态的 store,包含递增、递减功能。

定义 Store

新建 stores/counter.js

import { defineStore } from 'pinia'

// 用 defineStore 定义 store,第一个参数是唯一 ID(必须)
export const useCounterStore = defineStore('counter', {
  // 状态(初始数据)
  state: () => ({
    count: 0,
    title: '计数器'
  }),

  // 计算属性(派生状态)
  getters: {
    // 带参数的 getter(需返回函数)
    doubleCount: (state) => state.count * 2,
    // 依赖其他 getter
    doubleCountPlusOne: (state, getters) => getters.doubleCount + 1
  },

  // 方法(修改状态)
  actions: {
    increment() {
      // 直接修改 state(Pinia 会自动追踪)
      this.count++
    },
    decrement() {
      this.count--
    },
    // 带参数的 action
    incrementBy(num) {
      this.count += num
    }
  }
})
在组件中使用 Store

在任意组件中导入并使用上述 store:

<!-- CounterComponent.vue -->
<template>
  <div>
    <h2>{{ counterStore.title }}</h2>
    <p>当前值:{{ counterStore.count }}</p>
    <p>翻倍后:{{ counterStore.doubleCount }}</p>
    <p>翻倍+1{{ counterStore.doubleCountPlusOne }}</p>
    <button @click="counterStore.increment">+1</button>
    <button @click="counterStore.decrement">-1</button>
    <button @click="counterStore.incrementBy(5)">+5</button>
  </div>
</template>

<script setup>
// 导入 store
import { useCounterStore } from '@/stores/counter'

// 获取 store 实例(响应式)
const counterStore = useCounterStore()
</script>
4. 示例 2:异步数据 Store

创建一个获取用户信息的 store,演示 actions 处理异步逻辑。

定义 Store

新建 stores/user.js

import { defineStore } from 'pinia'
import axios from 'axios' // 假设用 axios 请求接口

export const useUserStore = defineStore('user', {
  state: () => ({
    userInfo: null, // 用户信息
    loading: false, // 加载状态
    error: null // 错误信息
  }),

  getters: {
    // 派生用户名称(处理 null 情况)
    userName: (state) => state.userInfo?.name || '未知用户'
  },

  actions: {
    // 异步获取用户信息(支持 async/await)
    async fetchUserInfo(userId) {
      try {
        this.loading = true
        this.error = null
        // 发起请求
        const res = await axios.get(`/api/users/${userId}`)
        // 修改状态
        this.userInfo = res.data
      } catch (err) {
        this.error = '获取用户信息失败'
        console.error(err)
      } finally {
        this.loading = false
      }
    },
    // 清除用户信息
    clearUser() {
      this.userInfo = null
    }
  }
})
在组件中使用异步 Store
<!-- UserComponent.vue -->
<template>
  <div>
    <button @click="fetchUser">获取用户信息</button>
    <button @click="userStore.clearUser">清除</button>

    <div v-if="userStore.loading">加载中...</div>
    <div v-if="userStore.error" style="color: red">{{ userStore.error }}</div>
    <div v-if="userStore.userInfo">
      <p>姓名:{{ userStore.userName }}</p>
      <p>年龄:{{ userStore.userInfo.age }}</p>
    </div>
  </div>
</template>

<script setup>
import { useUserStore } from '@/stores/user'

const userStore = useUserStore()

// 调用异步 action
const fetchUser = () => {
  userStore.fetchUserInfo(123) // 假设用户 ID 为 123
}
</script>

总结

Pinia 相比 Vuex 更简洁、灵活,通过 state 存储数据,getters 处理计算逻辑,actions 处理同步/异步操作,且天然支持 TypeScript 和 Vue 3 的 Composition API。实际开发中,建议按业务模块拆分多个 store(如 userStorecartStore),使状态管理更清晰。

演示了为无线无人机电池充电设计的感应电力传输(IPT)系统 Dynamic Wireless Charging for (UAV) using Inductive Coupling 模拟了为无人机(UAV)量身定制的无线电力传输(WPT)系统。该模型演示了直流电到高频交流电的转换,通过磁共振在气隙中无线传输能量,以及整流回直流电用于电池充电。 系统拓扑包括: 输入级:使用IGBT/二极管开关连接到全桥逆变器的直流电压源(12V)。 开关控制:脉冲发生器以85 kHz(周期:1/85000秒)的开关频率运行,这是SAE J2954无线充电标准的标准频率。 耦合级:使用互感和线性变压器块来模拟具有特定耦合系数的发射(Tx)和接收(Rx)线圈。 补偿:包括串联RLC分支,用于模拟谐振补偿网络(将线圈调谐到谐振频率)。 输出级:桥式整流器(基于二极管),用于将高频交流电转换回直流电,以供负载使用。 仪器:使用示波器块进行全面的电压和电流测量,用于分析输入/输出波形和效率。 模拟详细信息: 求解器:离散Tustin/向后Euler(通过powergui)。 采样时间:50e-6秒。 4.主要特点 高频逆变:模拟85 kHz下IGBT的开关瞬态。 磁耦合:模拟无人机着陆垫和机载接收器之间的松耦合行为。 Power GUI集成:用于专用电力系统离散仿真的设置。 波形分析:预配置的范围,用于查看逆变器输出电压、初级/次级电流和整流直流电压。 5.安装与使用 确保您已安装MATLAB和Simulink。 所需工具箱:必须安装Simscape Electrical(以前称为SimPowerSystems)工具箱才能运行sps_lib块。 打开文件并运行模拟。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值