Skip to content

setActivePinia()

setActivePinia() 函数允许你手动设置活动的 Pinia 实例。这在需要控制使用哪个 Pinia 实例的特定场景中很有用。

函数签名

ts
function setActivePinia(pinia: Pinia | undefined): Pinia | undefined

参数

  • pinia: Pinia | undefined - 要设置为活动的 Pinia 实例,或 undefined 来清除活动实例

返回值

  • 类型: Pinia | undefined
  • 描述: 之前活动的 Pinia 实例,如果没有则返回 undefined

基础用法

设置活动实例

js
import { createPinia, setActivePinia } from 'pinia'

const pinia = createPinia()
setActivePinia(pinia)

// 现在这个 pinia 实例是活动的
// 在此之后创建的 store 将使用这个实例

获取之前的实例

js
import { createPinia, setActivePinia } from 'pinia'

const pinia1 = createPinia()
const pinia2 = createPinia()

setActivePinia(pinia1)
const previousPinia = setActivePinia(pinia2)

console.log(previousPinia === pinia1) // true

常见用例

1. 测试场景

在测试中,你经常需要为每个测试创建一个新的 Pinia 实例:

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

describe('Store 测试', () => {
  beforeEach(() => {
    // 为每个测试创建一个新的 Pinia 实例
    const pinia = createPinia()
    setActivePinia(pinia)
  })

  it('应该使用新的 store', () => {
    const store = useMyStore()
    // 测试你的 store...
  })
})

2. 服务端渲染 (SSR)

在 SSR 上下文中,你可能需要为不同的请求设置不同的 Pinia 实例:

js
// server.js
import { createPinia, setActivePinia } from 'pinia'

app.use('*', (req, res, next) => {
  // 为每个请求创建一个新的 Pinia 实例
  const pinia = createPinia()
  setActivePinia(pinia)
  
  // 将实例存储在请求上下文中
  req.pinia = pinia
  next()
})

3. 多个应用实例

当使用多个 Vue 应用实例时:

js
import { createApp } from 'vue'
import { createPinia, setActivePinia } from 'pinia'

// 第一个应用
const app1 = createApp(App1)
const pinia1 = createPinia()
app1.use(pinia1)

// 第二个应用使用不同的 Pinia 实例
const app2 = createApp(App2)
const pinia2 = createPinia()
setActivePinia(pinia2)
app2.use(pinia2)

4. 插件开发

当开发需要与 Pinia 配合工作的插件时:

js
function myPiniaPlugin(context) {
  // 保存当前活动实例
  const previousPinia = setActivePinia(context.pinia)
  
  try {
    // 使用特定的 Pinia 实例进行插件工作
    // ...
  } finally {
    // 恢复之前的活动实例
    setActivePinia(previousPinia)
  }
}

高级用法

临时实例切换

js
import { createPinia, setActivePinia, getActivePinia } from 'pinia'

function withPiniaInstance(pinia, callback) {
  const previousPinia = getActivePinia()
  setActivePinia(pinia)
  
  try {
    return callback()
  } finally {
    setActivePinia(previousPinia)
  }
}

// 使用方式
const tempPinia = createPinia()
const result = withPiniaInstance(tempPinia, () => {
  const store = useMyStore()
  return store.someComputation()
})

实例隔离

js
class PiniaManager {
  constructor() {
    this.instances = new Map()
  }
  
  createInstance(key) {
    const pinia = createPinia()
    this.instances.set(key, pinia)
    return pinia
  }
  
  useInstance(key) {
    const pinia = this.instances.get(key)
    if (pinia) {
      setActivePinia(pinia)
    }
    return pinia
  }
  
  destroyInstance(key) {
    this.instances.delete(key)
  }
}

const manager = new PiniaManager()
manager.createInstance('main')
manager.createInstance('admin')

// 切换到管理员实例
manager.useInstance('admin')
const adminStore = useAdminStore()

// 切换到主实例
manager.useInstance('main')
const mainStore = useMainStore()

错误处理

检查活动实例

js
import { getActivePinia, setActivePinia } from 'pinia'

function ensureActivePinia() {
  if (!getActivePinia()) {
    console.warn('未找到活动的 Pinia 实例,正在创建一个...')
    const pinia = createPinia()
    setActivePinia(pinia)
    return pinia
  }
  return getActivePinia()
}

安全实例设置

js
function safeSetActivePinia(pinia) {
  try {
    return setActivePinia(pinia)
  } catch (error) {
    console.error('设置活动 Pinia 实例失败:', error)
    return undefined
  }
}

TypeScript 用法

ts
import { Pinia, createPinia, setActivePinia } from 'pinia'

function createAndSetPinia(): Pinia {
  const pinia: Pinia = createPinia()
  const previous: Pinia | undefined = setActivePinia(pinia)
  
  if (previous) {
    console.log('替换了之前的 Pinia 实例')
  }
  
  return pinia
}

// 类型安全的实例管理器
class TypedPiniaManager {
  private instances = new Map<string, Pinia>()
  
  createInstance(key: string): Pinia {
    const pinia = createPinia()
    this.instances.set(key, pinia)
    return pinia
  }
  
  setActive(key: string): Pinia | undefined {
    const pinia = this.instances.get(key)
    if (pinia) {
      return setActivePinia(pinia)
    }
    return undefined
  }
}

最佳实践

1. 始终恢复之前的实例

当临时更改活动实例时,始终恢复之前的实例:

js
// 正确
const previous = setActivePinia(tempPinia)
try {
  // 使用临时实例进行工作
} finally {
  setActivePinia(previous)
}

// 错误 - 不恢复
setActivePinia(tempPinia)
// 进行工作...
// 之前的实例丢失了

2. 在设置函数中使用

优先在设置函数中设置活动 Pinia,而不是在模块加载期间:

js
// 正确
function setupApp() {
  const pinia = createPinia()
  setActivePinia(pinia)
  const app = createApp(App)
  app.use(pinia)
  return app
}

// 避免 - 在模块加载时设置
const pinia = createPinia()
setActivePinia(pinia) // 这会立即运行

3. 不再需要时清除

js
function cleanup() {
  // 关闭时清除活动实例
  setActivePinia(undefined)
}

4. 记录实例切换

js
/**
 * 临时切换到管理员 Pinia 实例
 * 用于管理操作
 */
function withAdminContext(callback) {
  const previous = setActivePinia(adminPinia)
  try {
    return callback()
  } finally {
    setActivePinia(previous)
  }
}

常见陷阱

1. 忘记恢复

js
// 错误 - 之前的实例丢失
setActivePinia(newPinia)
doSomething()

// 正确 - 恢复之前的实例
const previous = setActivePinia(newPinia)
try {
  doSomething()
} finally {
  setActivePinia(previous)
}

2. 在模块加载期间设置

js
// 有问题 - 在导入时运行
const pinia = createPinia()
setActivePinia(pinia)

// 更好 - 在需要时设置
export function initializePinia() {
  const pinia = createPinia()
  setActivePinia(pinia)
  return pinia
}

3. 不处理 undefined

js
// 错误 - 不处理 undefined
function switchInstance(pinia) {
  setActivePinia(pinia) // pinia 可能是 undefined
}

// 正确 - 处理 undefined 情况
function switchInstance(pinia) {
  if (pinia) {
    setActivePinia(pinia)
  } else {
    console.warn('无法设置 undefined 的 Pinia 实例')
  }
}

相关函数

相关链接

Released under the MIT License.