qiankun 微前端事件通信指南:4 种场景一次讲清
qiankun 微前端事件通信指南:4 种场景一次讲清
【免费下载链接】qiankun📦 🚀 Blazing fast, simple and complete solution for micro frontends.项目地址: https://gitcode.com/gh_mirrors/qi/qiankun
qiankun 微前端事件通信绕不开一个现实:主应用和微应用各跑在独立的 JS 沙箱里,window互相隔离,数据必须走显式通道。本文按初始化传值、运行时喊话、全局状态共享、浏览器原生通道 4 个场景递进,把该用的手段一次讲清。
① 初始化阶段:把数据塞进微应用
最简单的通信发生在加载那一刻:loadMicroApp的props参数。主应用把数据和回调函数一次传入,微应用在mount生命周期接收。
// 主应用 const app = loadMicroApp({ name: 'profile', entry: '//localhost:8080', container, props: { user, onSignOut: signOutCurrentUser }, }); // 微应用 export async function mount(props) { renderProfile(props.container, { user: props.user }); props.onSignOut; // 回调也在 props 里 }注意这里:props是挂载时的一次性快照,之后变了不会自动推送。数据后续变化要走update推新快照;回调则给微应用留了一条"上报"的单向通道。
② 运行时:让任意应用喊话给其他应用
框架内事件:props 注入事件总线
qiankun v3 不再内置 2.x 时代的全局状态 API,官方推荐的"喊话"方式是:主应用创建一个事件总线实例,通过props传给各微应用。总线可以用 mitt 或原生EventTarget,接口统一是"派发事件 + 订阅事件"。
// 主应用 const bus = mitt(); loadMicroApp({ name: 'profile', entry, container, props: { bus } }); // 微应用:mount 时订阅,unmount 时移除 bus.on('logout', onLogout); bus.emit('tab-changed', { activeId: 'orders' });这条路线事件名和负载都由主应用集中约定,类型上好约束;卸载时务必移除监听器,否则卸载的应用会被总线一直持有。
DOM 层事件:CustomEvent
如果不想引第三方库,或者微应用内部已经用document事件做内部解耦,可以直接在document上派发自定义事件,主应用监听同名事件即可。适合"发出去不用回音"的松耦合通知:主应用只依赖事件名,不依赖微应用导出了什么。缺点是事件名是字符串约定、没有类型约束,负载复杂时不如总线好治理。
③ 全局状态:多个微应用共享同一份数据
你可能会问:既然 props 能传数据,为什么还专门搞共享状态?因为props传不了动态状态——它只在挂载时是快照,登录态、购物车这类持续变化的数据,靠反复调update推快照既不优雅也容易漏。
解法是:主应用持有一份 store,通过props把 store 和 dispatch 发给每个微应用,大家读写同一份数据。Redux、Zustand 或自写订阅器都行,qiankun 不限制具体实现。
// 主应用 const store = createStore(rootReducer); loadMicroApp({ name: 'profile', entry, container, props: { store, dispatch: store.dispatch } }); // 微应用 let unsubscribe; export async function mount({ store, dispatch }) { render(store.getState()); unsubscribe = store.subscribe(render); dispatch({ type: 'USER_LOGIN', payload: { name: 'Ada' } }); } export async function unmount() { unsubscribe?.(); }注意这里的清理义务:订阅注册在主应用的 store 上,unmount里不调unsubscribe,卸载的应用就会被监听器持有,内存泄漏就是这么来的。
④ 脱离框架:BroadcastChannel 跨上下文通信
BroadcastChannel是浏览器原生通道,零 qiankun API 依赖,同源的不同上下文(页面、iframe、Worker、甚至其他标签页)都能收到消息。它特别适合混合架构:主应用里既有 qiankun 加载的 ESM 微应用,又有 iframe 子应用,或者把重计算放进了 Web Worker。
// 主应用与微应用 / iframe 子应用各建同名 channel const channel = new BroadcastChannel('app-bus'); channel.postMessage({ type: 'USER_LOGOUT' }); channel.onmessage = (e) => console.log(e.data);两个约束:消息载荷必须可序列化;跨上下文的消息 schema 建议像props类型一样明确约定,方便排查和演进。
⑤ 怎么选?一张表说清
| 方案 | 通信方向 | 是否依赖 qiankun | 典型场景 | 一句话优劣 |
|---|---|---|---|---|
props传递 | 主 → 微(回调反向) | 是 | 初始化数据、上报回调 | 最显式好治理;仅挂载时生效,单向 |
| 事件总线(props 注入) | 应用间任意方向 | 总线实例由主应用创建 | 运行时通知、多应用响应同一事件 | 双向灵活、事件名可集中约定;订阅要手动清理 |
| 共享 store(Redux / Vuex 思路) | 围绕主应用的单一数据源 | 否,任何状态库 | 登录态、购物车等持续变化的全局状态 | 状态有唯一归属;需自行管理订阅与取消 |
BroadcastChannel | 同源跨上下文广播 | 完全独立 | 混合架构:qiankun + iframe / Web Worker | 零依赖、能跨标签页;消息必须可序列化 |
实际项目里通常是组合拳:props打底传初始数据,事件总线负责运行时通知,复杂状态交给主应用的 store,边界上再嵌了 iframe 就用BroadcastChannel。判断标准只有一条——状态和事件的归属要唯一,微应用只拿它需要的接口,而不是共享一整个window。更多通信约定见 官方文档。
【免费下载链接】qiankun📦 🚀 Blazing fast, simple and complete solution for micro frontends.项目地址: https://gitcode.com/gh_mirrors/qi/qiankun
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考