深入浅出 Pinia:Vue 的现代化状态管理方案

32 阅读2分钟

Pinia 是 Vue.js 生态中备受推崇的状态管理库,它提供了简洁、直观且类型安全的状态管理方案,逐渐成为 Vue 应用开发的首选。本文将基于官方文档,全面介绍 Pinia 的核心概念与使用方式。

一、Pinia 环境搭建

安装与配置

要在 Vue 项目中使用 Pinia,只需两步:

  1. 使用 npm 安装 Pinia:

bash

复制下载

npm install pinia
  1. 在 main.ts 中创建并注册 Pinia:

typescript

复制下载

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

const pinia = createPinia()
const app = createApp(App)

app.use(pinia)  // 注册 Pinia 插件
app.mount('#app')

完成配置后,Vue Devtools 中将出现 Pinia 选项,方便进行状态调试。

二、核心概念:Store 的创建与使用

Store 是 Pinia 的核心,它是一个保存状态和业务逻辑的实体。每个组件都可以读取和写入 Store,类似于组件中的 data、computed 和 methods 的组合。

创建 Store

Pinia 提供了两种 Store 创建方式:选项式和组合式。

1. 选项式 Store(推荐初学者)

typescript

复制下载

// src/store/count.ts
import { defineStore } from 'pinia'

export const useCountStore = defineStore('count', {
  // 状态(相当于 data)
  state: () => ({
    sum: 6
  }),
  
  // 计算属性(相当于 computed)
  getters: {},
  
  // 方法(相当于 methods)
  actions: {}
})

// src/store/talk.ts
export const useTalkStore = defineStore('talk', {
  state: () => ({
    talkList: [
      { id: 'yuysada01', content: '你今天有点怪,哪里怪?怪好看的!' },
      { id: 'yuysada02', content: '草莓、蓝莓、蔓越莓,你想我了没?' },
      { id: 'yuysada03', content: '心里给你留了一块地,我的死心塌地' }
    ]
  })
})

2. 组合式 Store(Vue 3 风格)

typescript

复制下载

import { defineStore } from 'pinia'
import { reactive } from 'vue'

export const useTalkStore = defineStore('talk', () => {
  const talkList = reactive(
    JSON.parse(localStorage.getItem('talkList') as string) || []
  )
  
  async function getATalk() {
    // 异步逻辑
  }
  
  return { talkList, getATalk }
})

在组件中使用 Store

vue

复制下载

<template>
  <h2>当前求和为:{{ countStore.sum }}</h2>
  <ul>
    <li v-for="talk in talkStore.talkList" :key="talk.id">
      {{ talk.content }}
    </li>
  </ul>
</template>

<script setup lang="ts">
import { useCountStore } from '@/store/count'
import { useTalkStore } from '@/store/talk'

const countStore = useCountStore()
const talkStore = useTalkStore()
</script>

三、状态修改的三种方式

Pinia 提供了灵活的状态修改方式:

1. 直接修改(简单场景)

typescript

复制下载

countStore.sum = 666

2. 批量修改(性能优化)

typescript

复制下载

countStore.$patch({
  sum: 999,
  school: 'atguigu'
})

3. 通过 Action 修改(业务逻辑封装)

typescript

复制下载

// 在 Store 中定义 actions
export const useCountStore = defineStore('count', {
  state: () => ({ sum: 0 }),
  actions: {
    increment(value: number) {
      if (this.sum < 10) {
        this.sum += value
      }
    },
    decrement(value: number) {
      if (this.sum > 1) {
        this.sum -= value
      }
    }
  }
})

// 在组件中调用
const countStore = useCountStore()
countStore.increment(5)

四、响应式辅助工具

storeToRefs

将 Store 中的状态转换为 ref 对象,保持响应式的同时方便解构:

vue

复制下载

<template>
  <h2>当前求和为:{{ sum }}</h2>
</template>

<script setup lang="ts">
import { useCountStore } from '@/store/count'
import { storeToRefs } from 'pinia'

const countStore = useCountStore()
const { sum } = storeToRefs(countStore)  // 保持响应式
</script>

五、Getters:计算状态

Getters 用于派生状态,当 state 需要处理后再使用时特别有用:

typescript

复制下载

export const useCountStore = defineStore('count', {
  state: () => ({
    sum: 1,
    school: 'atguigu'
  }),
  getters: {
    // 使用 state 参数
    bigSum: (state): number => state.sum * 10,
    
    // 使用 this 访问
    upperSchool(): string {
      return this.school.toUpperCase()
    }
  }
})

// 组件中使用
const { bigSum, upperSchool } = storeToRefs(countStore)

六、状态监听与持久化

$subscribe 监听状态变化

typescript

复制下载

talkStore.$subscribe((mutate, state) => {
  console.log('状态变化:', mutate, state)
  // 状态持久化
  localStorage.setItem('talk', JSON.stringify(talkList.value))
})

七、组合式 API 实践

组合式 Store 写法更加灵活,适合复杂场景:

typescript

复制下载

export const useTalkStore = defineStore('talk', () => {
  const talkList = reactive(
    JSON.parse(localStorage.getItem('talkList') as string) || []
  )
  
  async function getATalk() {
    const { data: { content: title } } = await axios.get(
      'https://api.uomg.com/api/rand.qinghua?format=json'
    )
    const obj = { id: nanoid(), title }
    talkList.unshift(obj)
  }
  
  return { talkList, getATalk }
})

总结

Pinia 以其简洁的 API、优秀的 TypeScript 支持和灵活的架构设计,为 Vue 应用提供了强大的状态管理能力。无论是简单的状态共享还是复杂的业务逻辑封装,Pinia 都能提供优雅的解决方案。通过本文的介绍,相信你已经掌握了 Pinia 的核心用法,可以开始在项目中实践这一现代化的状态管理方案了。

核心优势:

  • 直观的 API 设计
  • 完整的 TypeScript 支持
  • 模块化结构
  • 轻量级且高性能
  • 与 Vue Devtools 完美集成