本文主要内容包括:如何在主应用里注册子应用?如何实现路由拦截?
注册子应用
先定义子应用列表。
export const subNavList = [
{
name: 'react15', // 子应用名称
activeRule: '/react15', // 激活路由
container: '#micro-container', // 展示子应用的容器
entry: '//localhost:9002/' // 子应用的入口
},
{
name: 'react16',
activeRule: '/react16',
container: '#micro-container',
entry: '//localhost:9003/'
},
{
name: 'vue2',
activeRule: '/vue2',
container: '#micro-container',
entry: '//localhost:9004/'
},
{
name: 'vue3',
activeRule: '/vue3',
container: '#micro-container',
entry: '//localhost:9005/'
},
]
// 子应用列表也可以存储在 window 中,但不推荐,容易造成全局变量污染。
// 这里把子应用列表放在 list 变量里,还添加了对应的 get 和 set 方法。
let list = []
/** 获取所有子应用列表 */
export const getList = () => list
/** 将需要注册的子应用列表放置到子应用容器里 */
export const setList = appList => list = appList
export const registerMicroApps = (appList) => {
setList(appList)
}
export const registerApp = (list) => {
// 注册到微前端框架里
registerMicroApps(list)
}
// 主应用 createApp 之前调用
registerApp(subNavList)
路由拦截
入口函数是 rewriteRouter。
// 子应用是否做了切换,window.__CURRENT_SUB_APP__ 保证只触发一次,后面会设置值
export const isTurnChild = () => {
if (window.__CURRENT_SUB_APP__ === window.location.pathname) {
return false
}
return true
}
export const turnApp = () => {
if (isTurnChild()) {
console.log('路由切换了');
}
}
// 给当前的路由跳转打补丁
export const patchRouter = (globalEvent, eventName) => {
return function() {
const e = new Event(eventName)
globalEvent.apply(this, arguments)
window.dispatchEvent(e)
}
}
// 重写 window 的路由跳转
const rewriteRouter = () => {
window.history.pushState = patchRouter(window.history.pushState, 'micro_push')
window.history.replaceState = patchRouter(window.history.replaceState, 'micro_replace')
// 通过监听自己创建的事件名称来添加回调函数 turnApp
window.addEventListener('micro_push', turnApp)
window.addEventListener('micro_replace', turnApp)
// 监听返回事件
window.onpopstate = () => {
turnApp()
}
}
// 实现路由拦截
rewriteRouter()