微前端路由

41 阅读2分钟

背景:Qiankun 只有一个子应用,主应用控制所有动态路由(包括子应用的所有路由)


📌 分析

  • 只有 一个 子应用(Vue2 )。
  • 主应用(Vue3) 统一管理 所有路由(包括子应用的路由)。
  • 子应用 不处理自己的路由,而是交由主应用管理。

官方文档较少​编辑

补充

  • 主应用 维护完整的 routes,包括主应用自己的页面和子应用的所有路由。
  • 子应用 只作为一个“页面”加载,不处理自己的路由,主应用通过 props 传递路由信息。

1️⃣ 主应用 router/index.js

import { createRouter, createWebHistory } from 'vue-router';
import Home from '@/views/Home.vue'; 
import SubAppContainer from '@/views/SubAppContainer.vue'; // 用于挂载子应用的组件

const routes = [
  { path: '/', component: Home },
  { path: '/sub-apps/:pathMatch(.*)*', component: SubAppContainer }, // 所有子应用的路由交给 SubAppContainer 处理
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

export default router;


2️⃣ 创建 views/SubAppContainer.vue

<template>
  <div>
    <h1>子应用</h1>
    <div id="subAppContainer"></div>
  </div>
</template>

<script>
import { watch, onMounted, onUnmounted } from 'vue';
import { loadMicroApp } from 'qiankun';
import { useRoute } from 'vue-router';

export default {
  setup() {
    const route = useRoute();
    let microApp = null;

    onMounted(() => {
      microApp = loadMicroApp({
        name: 'vueSubApp',
        entry: '//localhost:8081',
        container: '#subAppContainer',
        props: {
          basePath: route.fullPath // 传递当前路由给子应用
        }
      });
    });

    watch(() => route.fullPath, (newPath) => {
      if (microApp && microApp.update) {
        microApp.update({ basePath: newPath }); // 主应用切换路由时通知子应用
      }
    });

    onUnmounted(() => {
      if (microApp) microApp.unmount();
    });

    return {};
  }
};
</script>


3️⃣ 子应用 main.js

import { createApp } from 'vue';
import App from './App.vue';
import router from './router';

let instance = null;

function render(props = {}) {
  const { container, basePath } = props;

  router.replace(basePath || '/'); // 子应用使用主应用传递的路由

  instance = createApp(App);
  instance.use(router);
  instance.mount(container ? container.querySelector('#app') : '#app');
}

export async function bootstrap() {}

export async function mount(props) {
  render(props);
}

export async function unmount() {
  instance.unmount();
}


4️⃣ 子应用 router/index.js

import { createRouter, createWebHistory } from 'vue-router';
import PageA from '@/views/PageA.vue';
import PageB from '@/views/PageB.vue';

const routes = [
  { path: '/', redirect: '/pageA' },
  { path: '/pageA', component: PageA },
  { path: '/pageB', component: PageB }
];

const router = createRouter({
  history: createWebHistory(), // 直接使用 history 模式,主应用控制路径
  routes
});

export default router;