Skip to content

Pinia 架构分析

整体架构

Pinia 采用基于 Store 的架构,通过 Store、State、Getters 和 Actions 管理应用状态。

┌─────────────────────────────────────────────┐
│               Pinia Core                     │
├─────────────────────────────────────────────┤
│  1. Store (Store)                           │
│     - State (状态)                           │
│     - Getters (计算属性)                     │
│     - Actions (方法)                         │
├─────────────────────────────────────────────┤
│  2. Pinia Instance (Pinia 实例)              │
│     - State Management (状态管理)            │
│     - Plugin System (插件系统)               │
│     - DevTools Integration (DevTools 集成)   │
├─────────────────────────────────────────────┤
│  3. Reactivity (响应式)                     │
│     - Vue Reactivity (Vue 响应式)           │
│     - Computed (计算属性)                    │
│     - Watch (监听)                          │
└─────────────────────────────────────────────┘

核心组件

1. Store

Store 是 Pinia 的核心,包含状态、计算属性和方法。

职责:

  • 存储状态
  • 提供计算属性
  • 提供方法

关键方法:

javascript
export function defineStore(id, options) {
  const { state, getters, actions } = options
  
  return function useStore(pinia) {
    pinia = pinia || activePinia
    
    if (!pinia._s.has(id)) {
      createStore(id, state, getters, actions, pinia)
    }
    
    return pinia._s.get(id)
  }
}

function createStore(id, state, getters, actions, pinia) {
  const store = reactive({
    $id: id,
    $state: state ? state() : {},
    $patch: (partialStateOrMutator) => {
      // 更新状态
    }
  })
  
  // 添加 getters
  if (getters) {
    Object.keys(getters).forEach(key => {
      Object.defineProperty(store, key, {
        get: () => getters[key].call(store, store)
      })
    })
  }
  
  // 添加 actions
  if (actions) {
    Object.keys(actions).forEach(key => {
      store[key] = actions[key].bind(store)
    })
  }
  
  pinia._s.set(id, store)
  return store
}

优势:

  • 简洁:简洁的 API
  • 灵活:灵活的状态管理
  • 类型安全:完整的 TypeScript 支持

2. Pinia Instance

Pinia 实例管理所有 Store。

职责:

  • 管理 Store
  • 插件系统
  • DevTools 集成

关键方法:

javascript
export class Pinia {
  constructor() {
    this._s = new Map()  // Store 映射
    this.state = reactive({})  // 全局状态
    this._p = []  // 插件
  }
  
  // 安装 Pinia
  install(app) {
    app.provide(piniaSymbol, this)
    app.config.globalProperties.$pinia = this
  }
  
  // 使用插件
  use(plugin) {
    this._p.push(plugin)
    this._p.forEach(p => p({ pinia: this, app: this._a }))
  }
  
  // 获取 Store
  get store() {
    return this._s
  }
}

优势:

  • 集中管理:集中管理所有 Store
  • 插件系统:支持插件扩展
  • DevTools:与 Vue DevTools 集成

3. Reactivity

响应式系统使用 Vue 3 的响应式 API。

职责:

  • 响应式状态
  • 计算属性
  • 监听

关键方法:

javascript
import { reactive, computed, watch } from 'vue'

// 响应式状态
const state = reactive({
  count: 0
})

// 计算属性
const doubleCount = computed(() => state.count * 2)

// 监听
watch(
  () => state.count,
  (newVal, oldVal) => {
    console.log(`count changed from ${oldVal} to ${newVal}`)
  }
)

优势:

  • 高效:高效的响应式系统
  • 灵活:灵活的响应式 API
  • 类型安全:完整的类型推断

状态管理

State

javascript
export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
    name: 'Eduardo'
  })
})

Getters

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

Actions

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

插件系统

插件结构

javascript
export function createPiniaPlugin(options = {}) {
  return ({ pinia, app, store, options }) => {
    // 插件逻辑
  }
}

插件使用

javascript
const pinia = createPinia()

pinia.use(createPiniaPlugin({
  // 插件选项
}))

DevTools 集成

状态追踪

javascript
function setupDevtoolsPlugin(pinia) {
  if (!__DEV__) return
  
  const devtools = window.__VUE_DEVTOOLS_GLOBAL_HOOK__
  
  devtools.on('pinia:state', ({ id, state }) => {
    // 更新状态
  })
}

性能优化

1. 懒加载 Store

javascript
const store = useCounterStore()  // 懒加载

2. 按需订阅

javascript
watch(
  () => store.count,  // 只订阅 count
  (newVal) => {
    console.log(newVal)
  }
)

3. 计算属性缓存

javascript
const doubleCount = computed(() => store.count * 2)  // 自动缓存

总结

Pinia 的架构体现了以下特点:

  1. 简洁:简洁的 API
  2. 灵活:灵活的状态管理
  3. 类型安全:完整的 TypeScript 支持
  4. 响应式:使用 Vue 3 的响应式系统

理解 Pinia 的架构有助于更好地使用和优化 Pinia。

参考资源

架构师AI杜公众号二维码

扫描二维码关注"架构师AI杜"公众号,获取更多技术内容和最新动态