如何让AngularJS的ngRoute与react-router协同工作且无路由冲突?
解决方案
问题根源
你遇到的后退按钮失效问题核心原因有两个:
- AngularJS的ngRoute默认会监听全局
popstate事件,后退触发时ngRoute先截获请求,匹配到/newRoute路由后直接复用现有模板,不会通知React侧处理子路由变化 - 你当前的react-router
basename配置错误,和Angular侧定义的父路由路径不匹配
以下方案完全兼容你使用的AngularJS 1.5.6/1.8.x、react-router v5.2.1版本。
步骤1:修正react-router basename配置
把BrowserRouter的basename改为和Angular侧父路由完全一致的路径:
// React侧修改后代码 const RouteView = () => ( <Suspense fallback={<div>Loading...</div>}> <BrowserRouter basename="/newRoute"> <SomeComponent /> </BrowserRouter> </Suspense> );
注意:如果你的AngularJS开启的是hash路由模式(路径带#前缀),请将BrowserRouter替换为HashRouter,basename改为#/newRoute
步骤2:调整AngularJS路由配置,兼容子路径
给/newRoute路由添加通配符,让所有/newRoute开头的子路径都命中同一个Angular路由,同时禁止路由自动重载:
// Angular侧修改后路由配置 .when("/newRoute*", { template: '<div react-bridged-component data-component-name="RouteView"></div>', reloadOnSearch: false, // 禁止查询参数或子路径变化时重新加载Angular路由 })
步骤3:拦截AngularJS路由事件,避免冲突
在AngularJS的run块中监听路由变化事件,匹配到/newRoute开头的路径时,阻止Angular默认的路由处理逻辑,交给react-router处理:
app.run(['$rootScope', function($rootScope) { $rootScope.$on('$locationChangeStart', function(event, newUrl) { // 匹配/newRoute及其所有子路径 if (newUrl.indexOf('/newRoute') !== -1) { event.preventDefault(); } }); }])
可选兜底方案
如果以上配置后仍有异常,可以将BrowserRouter替换为MemoryRouter,手动同步react-router和浏览器历史状态,适合子模块完全独立不需要对外暴露路由的场景。
内容的提问来源于stack exchange,提问作者Mirel Vlad
相关产品推荐
相关产品推荐

