Something beautiful is on the way.

Vue3 Pina 使用指南

Pina 使用指南

Pina 是一个状态管理库,专为 Vue.js 应用程序设计。以下是 Pina 的主要使用方法和特性:

安装

npm install pinia
# 或
yarn add pinia

基本使用

1. 创建 Store

// stores/counter.js
import { defineStore } from 'pinia'

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

2. 在 Vue 应用中使用

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

const app = createApp(App)
app.use(createPinia())
app.mount('#app')

3. 在组件中使用 Store

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

const counter = useCounterStore()
</script>

<template>
  <div>Count: {{ counter.count }}</div>
  <div>Double: {{ counter.doubleCount }}</div>
  <button @click="counter.increment()">Increment</button>
</template>

核心概念

State

  • 存储应用程序的状态
  • 使用 store.$patch 可以批量更新状态
counter.$patch({
  count: counter.count + 1,
  name: 'new name'
})

Getters

  • 类似于计算属性
  • 可以接收参数
getters: {
  tripleCount: (state) => {
    return (multiplier) => state.count * multiplier
  }
}

Actions

  • 相当于组件中的 methods
  • 可以是异步的
actions: {
  async fetchUser() {
    this.user = await api.getUser()
  }
}

高级特性

插件系统

可以创建 Pinia 插件来扩展功能:

function myPiniaPlugin(context) {
  context.store.$subscribe((mutation, state) => {
    // 响应 store 变化
  })
  
  return { secret: 'the cake is a lie' }
}

const pinia = createPinia()
pinia.use(myPiniaPlugin)

服务端渲染 (SSR)

Pinia 支持 SSR,需要在 SSR 环境下进行适当配置。

与 Vuex 的比较优势

  • 更简单的 API
  • 更好的 TypeScript 支持
  • 更轻量
  • 模块化设计
  • 无嵌套模块结构

Pina 已成为 Vue 3 官方推荐的状态管理解决方案,适合大多数中小型应用。


在 Pinia 中动态新增 State

在 Pinia 中,你可以动态地向 store 添加新的 state 属性,但需要注意一些方法和限制。

方法一:使用 $patch 动态添加 state

const store = useSomeStore()

// 动态添加新状态
store.$patch({
  newState: '初始值'
})

方法二:直接赋值(不推荐)

const store = useSomeStore()

// 直接添加新属性(不推荐,可能失去响应性)
store.newState = '初始值'

方法三:使用 $state 替换整个状态

const store = useSomeStore()

// 替换整个状态对象
store.$state = {
  ...store.$state,
  newState: '初始值'
}

最佳实践:在 store 定义时预留或使用 TypeScript 接口

interface MyStoreState {
  existingState: string
  [key: string]: any // 允许动态属性
}

export const useMyStore = defineStore('myStore', {
  state: (): MyStoreState => ({
    existingState: ''
  })
})

注意事项

  1. 响应性:使用 $patch 方法可以确保新添加的状态保持响应性
  2. TypeScript 支持:动态添加的属性在 TypeScript 中会报类型错误,除非使用扩展接口
  3. 开发工具:动态添加的状态在 Pinia 开发工具中可能不会立即显示
  4. 替代方案:考虑使用 Map 或动态对象作为 state,而不是直接添加属性

推荐模式

如果你需要高度动态的状态,可以考虑这种模式:

export const useDynamicStore = defineStore('dynamic', {
  state: () => ({
    dynamicStates: {} as Record<string, any>
  }),
  actions: {
    addState(key: string, value: any) {
      this.dynamicStates = {
        ...this.dynamicStates,
        [key]: value
      }
    }
  }
})

这样既保持了类型安全,又能动态管理状态。

posted @ 2025-06-29 18:18  张朋举  阅读(334)  评论(0)    收藏  举报