使用Vuex和Onboard.js时触发Maximum call stack size exceeded报错
问题根因
Vuex 会自动为存入 state 的所有属性添加递归响应式代理,而 Onboard.js 返回的 wallet 对象内部存在大量循环引用(比如 provider 实例的内部自引用、关联 Onboard 实例的反向引用等),Vue 递归遍历对象做响应式劫持时就会触发死循环,最终抛出栈溢出错误。
解决方案
方案1(推荐):仅存储需要用到的字段
不要直接把整个 wallet 对象存入 state,只提取你业务中实际需要的字段存储,避免不必要的响应式遍历:
// subscriptions 中的 wallet 回调修改为 wallet: (wallet) => { // 只提取你需要的属性,比如钱包名称、provider实例、地址等 const walletInfo = { name: wallet.name, provider: wallet.provider } commit('SET_WALLET', walletInfo); localStorage.setItem('wallet', wallet.name); }
方案2:标记对象跳过响应式处理
如果确实需要存储完整的 wallet 对象,可以将对象标记为非响应式,跳过Vue的代理逻辑:
- 如果你使用 Vue2 + Vuex3,使用
Object.freeze()冻结对象:
// subscriptions 中的 wallet 回调修改为 commit('SET_WALLET', Object.freeze(wallet));
- 如果你使用 Vue3 + Vuex4,使用
markRaw标记非响应式:
// 首先从vue导入markRaw import { markRaw } from 'vue' // mutations 修改为 SET_WALLET(state, wallet) { state.wallet = markRaw(wallet); }
注意:冻结/标记为非响应式后,修改
wallet对象内部的属性不会触发视图更新,如果你有需要响应式的属性,请单独提取到state中存储。
额外提示:你当前代码中也将整个onboard实例存入了 state,同样存在循环引用导致爆栈的风险,建议也用同样的方式处理。
内容的提问来源于stack exchange,提问作者Javier Villanueva
相关产品推荐
相关产品推荐

