Pinia报错:getActivePinia()调用时无活跃实例,游戏循环状态访问问题
问题原因与解决方案
报错原因
你遇到的getActivePinia() was called but there was no active Pinia错误,核心问题是模块加载时机和Pinia初始化时机不匹配:
gameLoop.js里的const store = useBaseCampStore()写在了模块顶级作用域,当App.vue导入这个文件时,这行代码会立即执行。- 此时
main.js虽然已经创建了Pinia实例,但还没完成和Vue应用的上下文绑定(Pinia的激活是在组件挂载流程中完成的),所以useBaseCampStore()找不到有效的Pinia实例。 - 注释
onMounted再取消注释能运行,是因为此时模块已经加载完毕,Pinia也已经激活,重新执行时能正常获取到上下文。
修复方案
方案1:将Store获取移到循环函数内部
修改gameLoop.js,把Store的获取逻辑放到mainLoop函数里,确保只有在Pinia激活后才调用useStore:
import { useBaseCampStore } from "@/store/baseCamp"; var lastTime = null; var totalTime = 0; export function mainLoop() { // 在这里获取Store,此时Pinia已完成激活 const store = useBaseCampStore(); const { increaseResource } = store; const currentTime = performance.now(); if (lastTime === null) { lastTime = currentTime; } const deltaTime = currentTime - lastTime; updateGame(deltaTime, totalTime, increaseResource); totalTime += deltaTime; lastTime = currentTime; requestAnimationFrame(mainLoop); } // eslint-disable-next-line no-unused-vars function updateGame(deltaTime, totalTime, increaseResource) { increaseResource("wood", (1 / 1000) * deltaTime); }
方案2:在组件中获取Store后传入循环
在App.vue的setup中先获取Store,再把需要的方法传给mainLoop:
修改App.vue
<template> <StateTest /> </template> <script> import { onMounted } from "vue"; import { mainLoop } from "./gameLoop"; import { useBaseCampStore } from "./store/baseCamp"; import StateTest from "./components/StateTest.vue"; export default { setup() { const store = useBaseCampStore(); const { increaseResource } = store; onMounted(() => { requestAnimationFrame(() => mainLoop(increaseResource)); }); }, components: { StateTest, }, }; </script>
修改gameLoop.js
var lastTime = null; var totalTime = 0; export function mainLoop(increaseResource) { const currentTime = performance.now(); if (lastTime === null) { lastTime = currentTime; } const deltaTime = currentTime - lastTime; updateGame(deltaTime, totalTime, increaseResource); totalTime += deltaTime; lastTime = currentTime; requestAnimationFrame(() => mainLoop(increaseResource)); } // eslint-disable-next-line no-unused-vars function updateGame(deltaTime, totalTime, increaseResource) { increaseResource("wood", (1 / 1000) * deltaTime); }
底层逻辑解析
- Vue的模块导入是静态解析的,组件初始化前就会执行模块内的所有顶级代码。
- Pinia的
useStore函数依赖当前Vue应用的「活跃Pinia实例」,这个实例是在app.use(pinia)之后,组件挂载的过程中才会绑定到Vue的全局上下文里。 - 直接在模块顶级调用
useStore,相当于在Pinia还没完成初始化绑定的时候就去拿实例,自然会触发找不到active Pinia的错误。
内容的提问来源于stack exchange,提问作者Luke DeLong
相关产品推荐
相关产品推荐

