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
相关产品推荐
相关产品推荐

