Skip to content

createPinia()

创建一个可供应用程序使用的新 Pinia 实例。

签名

ts
function createPinia(): Pinia

返回值

一个具有以下属性和方法的新 Pinia 实例:

  • install: Vue 插件安装函数
  • use(): 添加插件的方法
  • state: 包含所有 store 状态的响应式对象
  • 用于 store 管理的内部属性

基本用法

Vue 3

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')

Vue 2

js
import Vue from 'vue'
import { createPinia, PiniaVuePlugin } from 'pinia'
import App from './App.vue'

Vue.use(PiniaVuePlugin)

const pinia = createPinia()

new Vue({
  el: '#app',
  pinia,
  render: h => h(App)
})

配置

添加插件

可以添加插件来自定义 Pinia 行为:

js
import { createPinia } from 'pinia'
import { createPersistedState } from 'pinia-plugin-persistedstate'

const pinia = createPinia()

// 添加持久化插件
pinia.use(createPersistedState({
  storage: sessionStorage,
  key: id => `pinia-${id}`
}))

// 添加自定义插件
pinia.use(({ store }) => {
  store.$router = router
  store.$api = api
})

开发工具

js
import { createPinia } from 'pinia'

const pinia = createPinia()

// 在开发环境启用开发工具
if (process.env.NODE_ENV === 'development') {
  pinia.use(({ store }) => {
    store._customProperties = new Set(['$router', '$api'])
  })
}

多个实例

你可以为应用程序的不同部分创建多个 Pinia 实例:

js
import { createPinia } from 'pinia'

// 主应用程序 pinia
const mainPinia = createPinia()

// 具有不同插件的管理面板 pinia
const adminPinia = createPinia()
adminPinia.use(adminPlugin)

// 使用不同的实例
app.use(mainPinia)
adminApp.use(adminPinia)

SSR(服务端渲染)

创建 SSR 兼容实例

js
// server.js
import { createPinia } from 'pinia'
import { createSSRApp } from 'vue'

export function createApp() {
  const app = createSSRApp({})
  const pinia = createPinia()
  
  app.use(pinia)
  
  return { app, pinia }
}

状态序列化

js
// server.js
import { renderToString } from '@vue/server-renderer'

const { app, pinia } = createApp()

// 渲染应用
const html = await renderToString(app)

// 序列化状态
const state = JSON.stringify(pinia.state.value)

// 发送到客户端
const fullHtml = `
  <div id="app">${html}</div>
  <script>
    window.__PINIA_STATE__ = ${state}
  </script>
`

客户端水合

js
// client.js
import { createApp } from './main'

const { app, pinia } = createApp()

// 从服务器状态水合
if (typeof window !== 'undefined' && window.__PINIA_STATE__) {
  pinia.state.value = window.__PINIA_STATE__
}

app.mount('#app')

测试

测试设置

js
import { createPinia, setActivePinia } from 'pinia'
import { beforeEach, describe, it } from 'vitest'

describe('Store 测试', () => {
  beforeEach(() => {
    // 为每个测试创建新的 pinia 实例
    const pinia = createPinia()
    setActivePinia(pinia)
  })
  
  it('应该工作', () => {
    const store = useMyStore()
    expect(store.count).toBe(0)
  })
})

模拟插件

js
import { createPinia } from 'pinia'
import { vi } from 'vitest'

function createTestPinia() {
  const pinia = createPinia()
  
  // 模拟外部依赖
  pinia.use(() => ({
    $api: {
      get: vi.fn(),
      post: vi.fn()
    },
    $router: {
      push: vi.fn(),
      replace: vi.fn()
    }
  }))
  
  return pinia
}

高级配置

自定义状态序列化

js
import { createPinia } from 'pinia'
import { ref } from 'vue'

function createCustomPinia() {
  const pinia = createPinia()
  
  // 复杂类型的自定义序列化
  pinia.use(({ store }) => {
    store.$serialize = () => {
      const state = { ...store.$state }
      // 自定义序列化逻辑
      if (state.date instanceof Date) {
        state.date = state.date.toISOString()
      }
      return state
    }
    
    store.$deserialize = (data) => {
      // 自定义反序列化逻辑
      if (typeof data.date === 'string') {
        data.date = new Date(data.date)
      }
      store.$patch(data)
    }
  })
  
  return pinia
}

性能监控

js
import { createPinia } from 'pinia'

function createMonitoredPinia() {
  const pinia = createPinia()
  
  pinia.use(({ store }) => {
    // 监控 action 性能
    store.$onAction(({ name, after, onError }) => {
      const start = Date.now()
      
      after(() => {
        const duration = Date.now() - start
        console.log(`Action ${name} 耗时 ${duration}ms`)
      })
      
      onError((error) => {
        console.error(`Action ${name} 失败:`, error)
      })
    })
    
    // 监控状态变化
    store.$subscribe((mutation, state) => {
      console.log('状态变化:', mutation.type, mutation.payload)
    })
  })
  
  return pinia
}

TypeScript

自定义属性类型

ts
import 'pinia'
import type { Router } from 'vue-router'
import type { AxiosInstance } from 'axios'

declare module 'pinia' {
  export interface PiniaCustomProperties {
    $router: Router
    $api: AxiosInstance
  }
}

// 现在 TypeScript 知道自定义属性
const pinia = createPinia()
pinia.use(({ store }) => {
  store.$router = router // ✅ 有类型
  store.$api = api       // ✅ 有类型
})

通用 Pinia 工厂

ts
interface PiniaConfig {
  plugins?: PiniaPlugin[]
  devtools?: boolean
}

function createConfiguredPinia(config: PiniaConfig = {}): Pinia {
  const pinia = createPinia()
  
  // 添加插件
  config.plugins?.forEach(plugin => {
    pinia.use(plugin)
  })
  
  // 配置开发工具
  if (config.devtools && process.env.NODE_ENV === 'development') {
    pinia.use(devtoolsPlugin)
  }
  
  return pinia
}

错误处理

全局错误处理器

js
import { createPinia } from 'pinia'

function createRobustPinia() {
  const pinia = createPinia()
  
  pinia.use(({ store }) => {
    // 全局错误处理
    store.$onAction(({ name, onError }) => {
      onError((error) => {
        console.error(`Store action ${name} 失败:`, error)
        
        // 报告给错误跟踪服务
        errorTracker.captureException(error, {
          tags: {
            store: store.$id,
            action: name
          }
        })
      })
    })
  })
  
  return pinia
}

回退状态

js
import { createPinia } from 'pinia'

function createFallbackPinia() {
  const pinia = createPinia()
  
  pinia.use(({ store, options }) => {
    // 添加回退状态
    store.$fallback = () => {
      if (typeof options.state === 'function') {
        store.$patch(options.state())
      }
    }
    
    // 关键错误时自动回退
    store.$onAction(({ name, onError }) => {
      onError((error) => {
        if (error.critical) {
          store.$fallback()
        }
      })
    })
  })
  
  return pinia
}

最佳实践

1. 每个应用一个实例

js
// ✅ 好 - 每个应用一个实例
const pinia = createPinia()
app.use(pinia)

// ❌ 避免 - 无理由的多个实例
const pinia1 = createPinia()
const pinia2 = createPinia()

2. 使用前配置

js
// ✅ 好 - 使用前配置
const pinia = createPinia()
pinia.use(persistencePlugin)
pinia.use(routerPlugin)
app.use(pinia)

// ❌ 避免 - 安装后添加插件
app.use(pinia)
pinia.use(latePlugin) // 可能不会影响现有 store

3. 环境特定配置

js
// ✅ 好 - 环境感知设置
const pinia = createPinia()

if (process.env.NODE_ENV === 'development') {
  pinia.use(loggerPlugin)
  pinia.use(devtoolsPlugin)
}

if (process.env.NODE_ENV === 'production') {
  pinia.use(analyticsPlugin)
  pinia.use(errorReportingPlugin)
}

4. 插件顺序很重要

js
// ✅ 好 - 逻辑插件顺序
const pinia = createPinia()
pinia.use(routerPlugin)      // 基础功能
pinia.use(persistencePlugin) // 依赖状态
pinia.use(loggerPlugin)      // 应该最后添加以完整记录

常见模式

工厂模式

js
function createAppPinia() {
  const pinia = createPinia()
  
  // 标准插件
  pinia.use(routerPlugin)
  pinia.use(persistencePlugin)
  
  // 环境特定
  if (import.meta.env.DEV) {
    pinia.use(loggerPlugin)
  }
  
  return pinia
}

// 用法
const pinia = createAppPinia()
app.use(pinia)

懒加载插件

js
async function createAsyncPinia() {
  const pinia = createPinia()
  
  // 动态加载插件
  if (shouldUsePersistence) {
    const { createPersistedState } = await import('pinia-plugin-persistedstate')
    pinia.use(createPersistedState())
  }
  
  return pinia
}

生命周期

安装

  1. createPinia() 创建新实例
  2. app.use(pinia) 安装插件
  3. Pinia 设置全局属性并提供实例

Store 创建

  1. defineStore() 注册 store 定义
  2. 首次调用 useStore() 创建 store 实例
  3. 插件应用到新 store
  4. Store 添加到 Pinia 实例

清理

  1. 应用卸载时,Pinia 清理所有 store
  2. Effect scope 被销毁
  3. 订阅被移除

另请参阅

Released under the MIT License.