这是我们的菜单路由数据结构:
准确获取页面 html#
如果没有配置,则尝试 option.url
地址获取 html
内容,但可能一些环境配置差异,会导致访问不到 index.html
。
通常我们使用 vue2/cli
的项目 devServer
会这样配置:
module.exports = defineConfig({
devServer: {
//...
proxy: {
}
}
})
当在微前端中,我们通常设置了 publicpath
,会导致访问 http://localhost:8001/subApp/[subAppName]/[history path]
路径时出现 Cannot GET /subApp/[subAppName]/[history path]
,这样的情况你可以这样解决:
module.exports = defineConfig({
devServer: {
//...
proxy: {
},
historyApiFallback: {
index: '/[subAppName]/[history path]/index.html'
},
}
})
但如果不熟悉这项配置,可能你需要特别设置 html
获取方式:
startApp({
url,
html: fetchHtml(remoteEntry),
// ...
})
export const fetchHtml = (htmlUrl) => {
return fetch(htmlUrl, {
headers: {
Accept: 'text/html',
},
})
.then((response) => {
if (response.status >= 400) {
throw new Error('加载异常' + response.status)
}
return response.text()
})
.catch((e) => {
return Promise.reject(e)
})
}
route.component 设置#
我们路由会分层级,比如 parent 会有 LayoutCompent 构成布局,具体 child 会在
在动态路径中,由于子应用路由要交给他自己路由体系,所以需要在主应用中关闭子路由渲染逻辑:
<div id="micro-app-container" v-if="isSubAppFirstLoad">正在加载子应用</div>
<router-view :key="key" v-else />
主应用面包屑的控制#
由于子应用中路由的跳转需要在主应用同步展开一排面包屑,目前想到的策略是在子应用中拦截所有路由变动,并通过 wujie event 通知主应用,主应用发起一次 $router.push 方法,从而将面包屑 UI 重新激活。
子应用路由变化:
router.beforeEach((to, from, next) => {
window.$wujie?.bus.$emit("wujie-route-change", to);
})
主应用通过 cachedSubAppViews 标识控制是否加载过 wujie 子应用,同时再根据 reloadSubAppViews 判断子应用内部路由的变化:
bus.$on('wujie-route-change', (to) => {
// 主应用还未加载过子应用
if (!this.cachedSubAppViews.includes(to.name)) {
// 主应用路由跳转子应用to路由,设定开关,防止重新再次加载 loadSubApp(更新bms面包屑菜单)
if (!this.reloadSubAppViews.includes(to.name)) {
this.reloadSubAppViews.push(to.name)
this.$router.push({ path: to.path, query: to.query })
}
}
})
当满足上述条件后,发起主应用路由跳转,由于主应用根本不存在此应用,则在路由 watch 的地方再结合 reloadSubAppViews 跳过路由渲染逻辑:
watch: {
$route(newVal) {
// 子应用内部路由组件渲染后,不再做子应用加载,但要重置 reloadSubAppViews
if (this.reloadSubAppViews.includes(newVal.name)) {
const index = this.reloadSubAppViews.indexOf(newVal.name)
this.reloadSubAppViews.splice(index, 1)
return
}
if (newVal.meta.isSubApp) {
setTimeout(() => {
// 确保 this.$route 更新完毕
this.loadSubApp()
}, 0)
}
},
},