You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3宿主微前端中如何用Vue Router导航React子应用路由

解决方案:Vue3宿主应用路由导航React子应用路由

针对Vue3作为宿主、React作为子应用的微前端路由协同问题,提供两种可行方案:


方案一:基于React BrowserRouter的自动适配(简洁版)

该方案利用React路由的basename属性与Vue路由的通配符匹配,实现路由自动同步,无需额外状态传递。

1. 修改React子应用配置

App.tsx

调整路由路径为相对路径,并设置basename为宿主路由前缀:

import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
import Login from './Login';
import LoginAdmin from './LoginAdmin';

function App() {
  return (
    <BrowserRouter basename="/auth">
      {/* 示例内部导航,直接使用React的Link即可 */}
      <div>
        <Link to="/login">普通登录</Link>
        <span> | </span>
        <Link to="/login/admin">管理员登录</Link>
      </div>
      <Routes>
        <Route path="/login" element={<Login />} />
        <Route path="/login/admin" element={<LoginAdmin />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;

bootstrap.tsx

新增unmount方法,用于路由切换时清理子应用:

import ReactDOM from 'react-dom/client';
import App from './App';

let rootInstance: ReactDOM.Root | null = null;

function mount(element: Element): void {
  rootInstance = ReactDOM.createRoot(element);
  rootInstance.render(<App />);
}

function unmount(element: Element): void {
  if (rootInstance) {
    rootInstance.unmount();
    rootInstance = null;
  }
}

if (isDev()) {
  const element = document.querySelector('#auth-service');
  if (element) mount(element);
}

export { mount, unmount };

2. 配置Vue3宿主路由

创建router/index.js

添加通配符路由匹配所有/auth/*路径:

import { createRouter, createWebHistory } from 'vue-router';
import Auth from '../components/Auth.vue';

const routes = [
  // 宿主其他路由...
  {
    path: '/auth/*', // 通配符匹配所有/auth下的子路径
    component: Auth
  }
];

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

export default router;

修改bootstrap.js

挂载Vue Router到应用:

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

const app = createApp(App);
app.use(router);
app.mount('#container-service');

3. 优化Vue的Auth组件

添加子应用的挂载与卸载逻辑:

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';

const authRef = ref(null);
let authApp = null;

onMounted(async () => {
  // 动态加载React子应用模块
  const { mount, unmount } = await import('auth/AuthApp');
  authApp = { mount, unmount };
  authApp.mount(authRef.value);
});

onUnmounted(() => {
  // 路由切换时卸载子应用,避免内存泄漏
  if (authApp) authApp.unmount(authRef.value);
});
</script>

<template>
  <div ref="authRef"></div>
</template>

方案二:宿主完全控制路由状态(可控版)

该方案通过React的MemoryRouter将路由状态托管给Vue Router,适合需要精细控制路由的场景。

1. 修改React子应用配置

App.tsx

使用MemoryRouter,接收宿主传递的路由信息与导航回调:

import { MemoryRouter, Routes, Route, useNavigate } from 'react-router-dom';
import Login from './Login';
import LoginAdmin from './LoginAdmin';

// 自定义导航组件,点击时调用宿主的路由跳转
const HostNavLink = ({ to, children }) => {
  const navigate = useNavigate();
  const handleClick = (e) => {
    e.preventDefault();
    // 调用宿主提供的全局导航方法
    if (window.$authNavigate) {
      window.$authNavigate(to);
    } else {
      navigate(to);
    }
  };
  return <a href={to} onClick={handleClick}>{children}</a>;
};

function App({ initialLocation }) {
  return (
    <MemoryRouter initialEntries={[initialLocation]}>
      <div>
        <HostNavLink to="/auth/login">普通登录</HostNavLink>
        <span> | </span>
        <HostNavLink to="/auth/login/admin">管理员登录</HostNavLink>
      </div>
      <Routes>
        <Route path="/auth/login" element={<Login />} />
        <Route path="/auth/login/admin" element={<LoginAdmin />} />
      </Routes>
    </MemoryRouter>
  );
}

export default App;

bootstrap.tsx

更新mount方法支持接收路由参数:

import ReactDOM from 'react-dom/client';
import App from './App';

let rootInstance: ReactDOM.Root | null = null;

function mount(element: Element, { initialLocation }) {
  rootInstance = ReactDOM.createRoot(element);
  rootInstance.render(<App initialLocation={initialLocation} />);
}

function unmount(element: Element) {
  if (rootInstance) {
    rootInstance.unmount();
    rootInstance = null;
  }
}

if (isDev()) {
  const element = document.querySelector('#auth-service');
  if (element) {
    mount(element, { initialLocation: window.location.pathname });
  }
}

export { mount, unmount };

2. 配置Vue3宿主路由

router/index.js

添加具体的路由映射:

import { createRouter, createWebHistory } from 'vue-router';
import Auth from '../components/Auth.vue';

const routes = [
  // 宿主其他路由...
  {
    path: '/auth/login',
    component: Auth
  },
  {
    path: '/auth/login/admin',
    component: Auth
  }
];

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

export default router;

修改bootstrap.js

暴露Vue Router到全局,供React子应用调用:

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

const app = createApp(App);
app.use(router);
app.mount('#container-service');

// 暴露路由实例到全局
window.$vueRouter = router;

3. 优化Vue的Auth组件

监听路由变化,同步到React子应用:

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

const route = useRoute();
const authRef = ref(null);
let authApp = null;

onMounted(async () => {
  const { mount, unmount } = await import('auth/AuthApp');
  authApp = { mount, unmount };
  
  // 初始化挂载,传递当前路由
  authApp.mount(authRef.value, {
    initialLocation: route.fullPath
  });

  // 注册全局导航回调
  window.$authNavigate = (path) => {
    window.$vueRouter.push(path);
  };
});

// 监听路由变化,更新React子应用路由
watch(route, (newRoute) => {
  if (authApp) {
    authApp.unmount(authRef.value);
    authApp.mount(authRef.value, {
      initialLocation: newRoute.fullPath
    });
  }
});

onUnmounted(() => {
  if (authApp) authApp.unmount(authRef.value);
  delete window.$authNavigate;
});
</script>

<template>
  <div ref="authRef"></div>
</template>

内容的提问来源于stack exchange,提问作者mohammad nowresideh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 23:20:17