MicroApp 落地方案踏坑总结
1. 如何用一个基座承载子应用所有的路由?
- 建立一个通用组件,如基座1
micro-one.vue
<template>
<div class="one-page-page">
{{ microappObj.dominanUrl }}
<micro-app
v-if="show"
:baseroute='microappObj.baseroute'
:name="microappObj.name"
:url="microappObj.dominanUrl"
:default-page="microappObj.defaultPage"
:data='microappObj'
></micro-app>
</div>
</template>
<script setup lang="ts" name="appone">
import { ref, reactive, onMounted, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { getToken } from '../utils/utils'
const route = useRoute()
const router = useRouter()
const show = ref(false)
const path = route.path.replace('/con', '')
const microappObj = reactive({
dominanUrl: `http://localhost:3000/con/#${path}`,
name: 'console',
baseroute: ``,
defaultPage: `http://localhost:3000/con/#${path}`,
token: getToken() || ''
})
onMounted(() => {
// microappObj.dominanUrl = `http://localhost:3000/console/#${path.value}`
// microappObj.defaultPage = `http://localhost:3000/console/#${path.value}`
show.value = true
})
</script>
<style scoped>
</style>
- vue-router 创建动态路由
routes.ts
添加
{
path: '/con/:page*',
name: 'con',
meta: {
title: 'app 新管理后台',
permiss: '2',
microapp: {
is: true,
}
},
component: () => import('../views/app-one.vue'),
},
注意这时候会出现一个大坑
组件micro-one.vue
跳转路由不更新监听不到路由地址变化,为什么呢?
答案: 因为路由是动态的,但是name 同一叫 ‘con’, 所以vue3 认为是同一个组件不进行更新变化
解决方案:
<router-view v-slot="{ Component, route }">
<transition name="move" mode="out-in">
<keep-alive :include="tags.nameList">
<component
ref="myComponent"
:is="Component"
:key="route.path"
></component>
<!-- -->
</keep-alive>
</transition>
</router-view>
// 将此代码改成
<router-view v-slot="{ Component, route }">
<transition name="move" mode="out-in">
<!-- <keep-alive :include="tags.nameList"> -->
<component
ref="myComponent"
:is="formatComponentInstance(Component, route)"
:key="route.path"
></component>
<!-- :is="Component" -->
<!-- </keep-alive> -->
</transition>
</router-view>
// js 部分添加
const wrapperMap = new Map();
// 将router传个我们的组件重新换一个新的组件,原组件包里面
function formatComponentInstance(component, route) {
let wrapper;
if (component) {
const wrapperName = route.path;
if (wrapperMap.has(wrapperName)) {
wrapper = wrapperMap.get(wrapperName);
} else {
wrapper = {
name: wrapperName,
render() {
return h(component);
},
};
wrapperMap.set(wrapperName, wrapper);
}
return h(wrapper);
}
}
踏坑2 如何通用token ?
- 主应用通过基座传递 data
<micro-app
v-if="show"
:baseroute='microappObj.baseroute'
:name="microappObj.name"
:url="microappObj.dominanUrl"
:default-page="microappObj.defaultPage"
:data='microappObj'
></micro-app>
- 子应用接收 data 数据
if ((window as any).__MICRO_APP_ENVIRONMENT__) {
const data = (window as any).microApp.getData()
if (data.token) {
document.cookie = `token=${data?.token}`;
document.cookie = `Admin-Token=${data?.token}`
}
console.log(data, '我在微前端环境中')
}
踏坑三 本地启用localhost 主应用端口衔接子应用端口,各自端口请求服务器接口都做了代理,但是子应用请求服务器接口在主应用里面跨域,怎么处理呢?
- 解决方案: 主应用进行接口代理,将主应用域传递给子应用,子应用的 basUrl 取主应用传递过去的