uni-app 小程序中将 pinia store 通过 props 传入插槽组件,组件内调用 actions 方法抛异常后,微信小程序真机会死循环导致页面卡死

发布于 1周前 作者 yuanlaile 来自 Uni-App

uni-app 小程序中将 pinia store 通过 props 传入插槽组件,组件内调用 actions 方法抛异常后,微信小程序真机会死循环导致页面卡死

示例代码:

报错示例代码见附件

附件项目如何使用:

  1. 下载zip压缩包,解压
  2. 在项目目录,使用yarn安装依赖
  3. 使用yarn dev:mp-weixin命令编译成微信小程序
  4. 打开微信开发者工具进行调试
  5. 微信开发者工具生成开发码,手机扫码,即可一键死机

操作步骤:

复现步骤(可参照附件项目,附件里的项目有完整复现方法):

  1. 创建一个Pinia的Store,里面定义一个Action方法,方法内抛出异常
  2. 创建父组件,在父组件内useStore,并存入对象,当做props传入子组件
  3. 创建子组件A,声明一个插槽
  4. 创建子组件B,子组件某个方法调用(通过props传入的)Store里的异常Action
  5. 在父组件使用子组件A,将子组件B传入子组件A的插槽内
  6. 使用真机调试微信小程序,触发报错Action,100%出现死循环卡顿,手机会发烫死机

预期结果:

预期结果:正常报错,但不会造成死循环并死机

实际结果:

触发报错Action,100%出现死循环卡顿,手机会发烫死机

bug描述:

Vue3+ts版复现该BUG
(项目由CLI创建,命令:npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project)

复现步骤(可参照附件项目,附件里的项目有完整复现方法):

  1. 创建一个Pinia的Store,里面定义一个Action方法,方法内抛出异常
  2. 创建父组件,在父组件内useStore,并存入对象,当做props传入子组件
  3. 创建子组件A,声明一个插槽
  4. 创建子组件B,子组件某个方法调用(通过props传入的)Store里的异常Action
  5. 在父组件使用子组件A,将子组件B传入子组件A的插槽内
  6. 使用真机调试微信小程序,触发报错Action,100%出现死循环卡顿,手机会发烫死机

附件项目如何使用:

  1. 下载zip压缩包,解压
  2. 在项目目录,使用yarn安装依赖
  3. 使用yarn dev:mp-weixin命令编译成微信小程序
  4. 打开微信开发者工具进行调试
  5. 微信开发者工具生成开发码,手机扫码,即可一键死机

uni-vue3-throw-error-loop.zip


8 回复

感谢反馈,这边排查下


已复现问题,与pinia无关,后续会修复。你可以先把错误捕获下

好的 谢谢!

您好,有具体修复发版时间吗

回复 f***@163.com: 我之前的回答有误,这个问题是pinia导致的,为什么要传递一个store呢?你直接在子组件引入试试

回复 YUANRJ: 因为业务需要,同样的interface可能传入的实现不同,所以需要传入,不太方便直接use去使用pinia store

回复 YUANRJ: 使用原生Vue没有复现这样的问题,只有uniapp微信的运行时环境上出现了这样的问题。麻烦修复这个死循环问题,支持下这样的用法。谢谢

在 uni-app 小程序中使用 Pinia 时,如果将 Pinia store 通过 props 传入插槽组件,并在组件内调用 store 的 actions 方法时抛出了异常,可能会导致微信小程序真机出现死循环,进而导致页面卡死。这个问题通常与异常处理不当或状态更新触发重新渲染有关。

以下是可能的原因和解决方案:


1. 异常未被捕获

如果 actions 方法抛出异常且未被捕获,可能会导致组件不断尝试重新执行该方法,从而进入死循环。

解决方案: 确保在调用 actions 方法时使用 try-catch 捕获异常,避免异常传播。

try {
  await store.someAction();
} catch (error) {
  console.error('Action failed:', error);
}

2. 状态更新触发重新渲染

如果 actions 方法中修改了 store 的状态,而状态更新又触发了组件的重新渲染,可能会导致组件不断调用 actions 方法,从而进入死循环。

解决方案: 检查 actions 方法中是否有不必要的状态更新,或者确保状态更新不会触发组件的重新渲染。


3. 插槽组件的重新渲染

如果 Pinia store 通过 props 传入插槽组件,而父组件的状态更新导致插槽组件不断重新渲染,可能会触发 actions 方法的重复调用。

解决方案:

  • 避免将 store 直接通过 props 传入插槽组件,而是直接在插槽组件内使用 Pinia 的 useStore 获取 store。
  • 使用 computedwatch 控制状态更新,避免不必要的重新渲染。
import { useStore } from '@/store';

export default {
  setup() {
    const store = useStore();
    return { store };
  },
};

4. 微信小程序的异常处理机制

微信小程序的异常处理机制可能与 Pinia 的行为不完全兼容,导致异常未被正确处理,从而引发死循环。

解决方案:

  • 确保 Pinia 和微信小程序的版本是最新的。
  • actions 方法中避免抛出同步异常,改为返回错误信息。

5. 调试与日志

启用详细的日志记录,帮助定位问题的根源。

解决方案:actions 方法和组件生命周期中添加日志,观察调用顺序和状态变化。

actions: {
  someAction() {
    console.log('Action called');
    try {
      // 业务逻辑
    } catch (error) {
      console.error('Action error:', error);
    }
  },
},
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!