路由与生命周期:主子和路由如何共存
本节目标
- 理解 activeRule 如何决定「何时挂哪个子应用」
- 会给子应用设置 base,避免路由冲突
- 知道子应用卸载时为什么要清状态
微前端的路由是个核心矛盾:基座有路由,子应用也有路由,两者怎么不打架? qiankun 的解法是「基座管一级路由(activeRule),子应用在自己的命名空间内管二级路由」。
// 基座:用 history 模式路由,activeRule 决定子应用边界
// 访问 /order/list → 命中 activeRule '/order' → 挂载 orderApp
registerMicroApps([
{ name: 'orderApp', entry: '//localhost:7100', container: '#subapp', activeRule: '/order' },
{ name: 'goodsApp', entry: '//localhost:7200', container: '#subapp', activeRule: '/goods' }
])// 子应用(Vue Router):必须把自己「钉」在 /order 命名空间下
// src/router.js
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
// base 要和基座 activeRule 一致,否则子应用内部跳转会跑到基座根路径
history: createWebHistory('/order'),
routes: [
{ path: '/list', component: OrderList }, // 实际访问 /order/list
{ path: '/detail/:id', component: OrderDetail }
]
})为什么必须设 base?如果子应用用根路径 /,它内部的 /list 会和基座的 / 冲突,浏览器地址会乱跳。把子应用「钉」在 /order 下,基座和子应用的路由各管一段,井水不犯河水。
生命周期还要注意卸载清理:用户从 /order 切到 /goods 时,qiankun 调用 orderApp 的 unmount。你必须在 unmount 里 app.unmount()、移除全局监听、清理定时器,否则子应用的 DOM 事件/定时器会残留在基座里,造成内存泄漏或「幽灵事件」。
名词解释
activeRule:基座注册子应用时写的「激活规则」,通常是路径前缀(如 /order)。当前 URL 匹配它,基座就挂载对应子应用。
base(路由基路径):子应用路由的命名空间前缀,要和基座的 activeRule 对齐,保证子应用内部跳转落在自己的区间内。
卸载清理(unmount cleanup):子应用离开时,必须销毁框架实例、移除监听、清定时器,否则会污染基座。
课后练习
练习 1:activeRule 写成 '/order' 和 '/order/' 有区别吗?
答案:有。qiankun 默认按下标匹配,
'/order'能命中/order和/order/list;具体匹配行为还受exactMatch等参数影响。一般写不带尾斜杠的前缀最稳,配合子应用 base 一致即可。
练习 2:子应用 unmount 里不清理 setInterval 会怎样?
答案:定时器仍在跑,且因为闭包持有子应用状态,DOM 已被卸载,定时器回调里操作已不存在的节点会报错,同时造成内存泄漏。所以
unmount里一定要clearInterval并app.unmount()。
总结
路由共存的口诀:基座用 activeRule 划地盘,子应用用 base 把自己钉进同一块地盘。两者路径前缀对齐,主子和路由各管一段、互不覆盖。别忘了 unmount 里做清理——这是微前端「切走还留坑」的头号来源。下一节进入更深的水:JS 沙箱和样式隔离。