微前端子应用间共享状态时,状态更新不同步怎么办?
我在用qiankun做微前端时,主应用和子应用通过window全局变量共享用户登录状态。但发现子应用修改状态后,其他子应用没及时更新,有时候刷新页面数据就丢失了。
比如主应用这样设置状态:
window.__GLOBAL_STATE__.user = {name: 'Alice', auth: true};
parent.postMessage({type: 'STATE_UPDATE'}, '*');
子应用用事件监听获取:
window.addEventListener('message', (e) => {
if(e.data.type === 'STATE_UPDATE') {
console.log('收到状态更新:', e.data.payload) // 这里经常拿不到最新数据
}
});
试过用localStorage做中间层,但频繁读写影响性能,而且子应用加载时初始化状态总是有延迟,有没有更可靠的共享方案?
按照规范,状态共享得用“发布-订阅”模型,而不是靠事件+全局变量这种“手写轮子”方式。qiankun 官方其实推荐用
props+useGlobalState的方式,或者直接用一个独立的状态库,比如zustand或micro-store。最简单的做法是:把状态中心化,放到一个独立的 JS 模块里,主应用和子应用都从这个模块里
get和set,模块内部用EventTarget或Proxy做依赖通知,而不是靠postMessage。举个最简实现(别写在全局污染 window):
主应用里:
子应用里(比如 React):
这样每个子应用自己订阅,状态更新是同步的,没有延迟,也不依赖事件顺序。子应用首次挂载时通过
getGlobalState()就能拿到最新值,不会丢。另外别用
localStorage做高频状态同步,除非你做的是离线优先的场景,那种开销确实大,而且容易触发浏览器节流。如果你们项目已经用了 qiankun,也可以考虑用它的
qiankun-vue或qiankun-react的官方状态共享方案,比如useGlobalState,但底层原理其实差不多,都是靠模块共享 + 订阅通知。别再靠
postMessage手动传 payload 了,那个太容易出错,特别是子应用加载时机不一致的时候。记得在每个子应用加载时主动拉取一次最新状态,避免初始化延迟问题。