应用间通信:全局状态、事件与共享 store

本节目标

子应用各自独立,但业务上常要互通:基座登录后要把 token 给子应用;子应用下单成功要通知基座刷新角标。三种常用手段:

1. qiankun 全局状态 initGlobalState(最常用)。基座建一个全局 store,主子和都能读能改:

// 基座
import { initGlobalState } from 'qiankun'
const actions = initGlobalState({ user: null, cartCount: 0 })
actions.onGlobalStateChange((state, prev) => {
  console.log('全局状态变了:', state, '上一个:', prev)
})
// 子应用 mount 时拿到 actions,读写全局状态
export async function mount(props) {
  props.onGlobalStateChange((state) => {
    console.log('子应用收到 user:', state.user)
  })
  props.setGlobalState({ cartCount: 3 }) // 子应用改全局状态
}

2. 自定义事件(轻量、解耦)。不想引入 qiankun 耦合时,用浏览器原生 CustomEvent 在 window 上广播:

// 子应用广播
window.dispatchEvent(new CustomEvent('order:paid', { detail: { id: 88 } }))
// 基座(或任意子应用)监听
window.addEventListener('order:paid', (e) => {
  console.log('收到支付事件:', e.detail.id)
})

3. 共享 store(重场景)。若多个子应用共用同一套状态(如都用同一个 Vuex/Redux 实例),可把 store 实例通过 props 注入各子应用,实现「真·共享同一份状态」。

数据怎么分?一次性初始化数据(token、theme)走 props;需要跨应用响应式同步的状态(用户信息、购物车角标)走 initGlobalState;一次性通知(下单成功)走自定义事件。

名词解释

initGlobalState:qiankun 提供的全局状态机制,基座创建后,主子和应用都能通过 onGlobalStateChange 监听、setGlobalState 修改,实现响应式互通。

onGlobalStateChange:订阅全局状态变化的回调,状态被任意一方修改都会触发,拿到「新值 + 旧值」。

CustomEvent(自定义事件):浏览器原生事件机制,适合「一次性通知」型通信,不依赖任何框架,解耦最彻底。

课后练习

练习 1:props 和 initGlobalState 该分别传什么?

答案:props 传「初始化就定好、不常变」的数据(token、theme、用户 id);initGlobalState 传「运行中会变化、多方要同步」的状态(购物车数量、登录态)。前者像构造参数,后者像响应式 store。

练习 2:自定义事件通信最大的坑是什么?

答案:监听要在 unmount 时 removeEventListener 移除,否则子应用切走后事件还在监听,再次进入会「重复绑定」导致回调触发多次。这是微前端事件通信最常见的内存泄漏点。

总结

通信三件套:initGlobalState 做响应式共享(主子互通)、CustomEvent 做一次性通知(解耦)、共享 store 做重场景的同份状态。口诀——「不变的走 props、变的走全局状态、通知走事件」,且事件监听务必在 unmount 清理。下一节进入现代最热的方向:Module Federation。