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 实例')
}
}
相关函数
getActivePinia()
- 获取当前活动的 Pinia 实例createPinia()
- 创建新的 Pinia 实例