Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

主应用和子应用都是用Vue3+VueRouter4,点击主应用中菜单进行router.push,对应同一个activeRule的子应用来回切换,会重复创建子应用实例 #1865

Open
huangxu510 opened this issue Dec 10, 2021 · 37 comments

Comments

@huangxu510
Copy link

huangxu510 commented Dec 10, 2021

What happens?

主应用和子应用都是用Vue3+VueRouter4,点击主应用中菜单进行router.push,对应同一个activeRule的子应用来回切换,会重复创建子应用实例
具体表现为

  1. 主应用 Vue2+VueRouter3 子应用Vue2+VueRouter3, 正常
  2. 主应用 Vue2+VueRouter3 子应用Vue3+VueRouter4, 正常
  3. 主应用 Vue3+VueRouter4 子应用Vue2+VueRouter3, 正常
  4. 主应用 Vue3+VueRouter4 子应用Vue3+VueRouter4, 来回切换会重复创建子应用实例

初步感觉是 VueRouter4 和 qiankun 之间的兼容问题,望排查修复

最小可复现仓库

https://github.com/huangxu510/qiankun-test/tree/master

复现步骤,错误日志以及相关配置

1.启动 vue2-base, vue3-base, vue-2-micro-app, vue3-micro-app
2.在vue3-base启动页面中,来回切换 vue3主页和vue3列表 菜单
3. 可以看到log里面乾坤的生命周期,每次来回切换都会创建子应用实例

image

相关环境信息

  • qiankun 版本 2.6.0
  • 浏览器版本 Chrome 96.0.4664.93
  • 操作系统 MacOS 11.6
@huangxu510
Copy link
Author

有大佬帮忙看看吗

@gongshun
Copy link
Collaborator

gongshun commented Dec 15, 2021

看了下,VueRouter4的问题,主应用跳转路由时,触发了一个错误的路由,single-spa 监听到了就卸载了子应用。

/vue3 跳转到 /vue3/list 时,中间会跳转到 /list(这一步会触发卸载),然后才跳转到 /vue3/list 。主应用的路由钩子没有监听到这个路由跳转,但是 single-spa 能监听到

@huangxu510
Copy link
Author

看了下,VueRouter4的问题,主应用跳转路由时,触发了一个错误的路由,single-spa 监听到了就卸载了子应用。

/vue3 跳转到 /vue3/list 时,中间会跳转到 /list(这一步会触发卸载),然后才跳转到 /vue3/list 。主应用的路由钩子没有监听到这个路由跳转,但是 single-spa 能监听到

我也看了下,VueRouter4push的时候调用了两个方法 一个replaceState,一个pushState,问题出在replaceState的时候,获取的state.current不对,是因为VueRouter4在histry.state里面有存一些值,然后主应用和子应用的histry.state没有隔离开,导致的这些值串了,获取的state(之前提到的state.current)就不对了

@huangxu510
Copy link
Author

看了下,VueRouter4的问题,主应用跳转路由时,触发了一个错误的路由,single-spa 监听到了就卸载了子应用。

/vue3 跳转到 /vue3/list 时,中间会跳转到 /list(这一步会触发卸载),然后才跳转到 /vue3/list 。主应用的路由钩子没有监听到这个路由跳转,但是 single-spa 能监听到

乾坤官网介绍特性说了 JS 沙箱,确保微应用之间 全局变量/事件 不冲突,现在这个问题的根本原因就是主应用和子应用的vue-router在window.history.state中存的变量相互影响了,那么其实还是乾坤js沙箱的问题吧,希望你们可以深入跟踪一下

@huangxu510
Copy link
Author

有大佬看看这问题吗,着急

@YueLiux
Copy link

YueLiux commented Jul 9, 2022

可以尝试在主应用菜单切换时直接使用 history.pushState();处理,绕过router。

@413362848
Copy link

413362848 commented Aug 3, 2022

主应用上跳转用 router.replace 这样的可以防止跳转到空页面 /list 但是会直接跳到vue3这个页面来 算是一个替代的办法

@coderja
Copy link

coderja commented Oct 8, 2022

我将pushState替换成replaceState可行

@lchxiang
Copy link

可以尝试在主应用菜单切换时直接使用 history.pushState();处理,绕过router。

切换应用的时候会出问题 比如 /app1/sys 切到/app2/sys 使用这个会跳转到 /app1/app2/sys这个地址导致错误

@cdxxiaomao
Copy link

我遇到的是,主应用与子应用都用的vueRouter4,发现点击主应用跳转,始终都会unmount然后mount,相当于是多次createApp,我在乾坤unmount的时候,把vue实例都进行了app.unmount(),问题得到了解决。

@Ashuangshuang
Copy link

@huangxu510 @gongshun
我现在也遇到了这个问题,主vue2+子vue3,子应用内部切换页面后还会导致返回上级页面路径变为/undefined,请问大佬们,这个问题解决了嘛?

@Matsumoto384
Copy link

可以尝试在主应用菜单切换时直接使用 history.pushState();处理,绕过router。

切换应用的时候会出问题 比如 /app1/sys 切到/app2/sys 使用这个会跳转到 /app1/app2/sys这个地址导致错误

请问有找到解决方法吗,我遇到了同样的问题

@hulong-prong
Copy link

解决了吗?我也遇到这个问题了

@hulong-prong
Copy link

怎么解决的

@cdxxiaomao
Copy link

qiankun 在切换至其他子系统的时候,会调用unmount,这个时候,记得卸载vue。如:

import {createApp} from "vue"

// 创建vue实例
const app = createApp()

// qiankun钩子,在切换子系统的时候qiankun会进行调用,这里记得卸载vue的实例;
export function unmount() {
   app.unmount()
}

@hulong-prong
Copy link

qiankun 在切换至其他子系统的时候,会调用unmount,这个时候,记得卸载vue。如:

import {createApp} from "vue"

// 创建vue实例
const app = createApp()

// qiankun钩子,在切换子系统的时候qiankun会进行调用,这里记得卸载vue的实例;
export function unmount() {
   app.unmount()
}

我在qiankun卸载的时候调用了app.unmount()的,问题是同一个activeRule下,不应该出现卸载

@hulong-prong
Copy link

有大佬看看这问题吗,着急

请问,你有解决这个问题吗

@huangxu510
Copy link
Author

有大佬看看这问题吗,着急

请问,你有解决这个问题吗

我暂时的解决方法修改了主应用中VueRouter的一段源码,具体是 注释掉 /node_modules/vue-router/dist/vue-router.esm-bundler.js 文件中 changeLocation(currentState.current, currentState, true); 这一行

@hulong-prong
Copy link

有大佬看看这问题吗,着急

请问,你有解决这个问题吗

我暂时的解决方法修改了主应用中VueRouter的一段源码,具体是 注释掉 /node_modules/vue-router/dist/vue-router.esm-bundler.js 文件中 changeLocation(currentState.current, currentState, true); 这一行

你的vueRouter 版本是多少

@hulong-prong
Copy link

有大佬看看这问题吗,着急

请问,你有解决这个问题吗

我暂时的解决方法修改了主应用中VueRouter的一段源码,具体是 注释掉 /node_modules/vue-router/dist/vue-router.esm-bundler.js 文件中 changeLocation(currentState.current, currentState, true); 这一行

我看了一下,发现是currentState 的地址有问题,因为子应用和主应用共用了history 导致子应用触发后会导致每次触发push 获取currentState 出现问题,然后导致了这个问题,还是隔离不够彻底的问题

@hulong-prong
Copy link

有大佬看看这问题吗,着急

请问,你有解决这个问题吗

我暂时的解决方法修改了主应用中VueRouter的一段源码,具体是 注释掉 /node_modules/vue-router/dist/vue-router.esm-bundler.js 文件中 changeLocation(currentState.current, currentState, true); 这一行

我看了一下,发现是currentState 的地址有问题,因为子应用和主应用共用了history 导致子应用触发后会导致每次触发push 获取currentState 出现问题,然后导致了这个问题,还是隔离不够彻底的问题

或者说在子应用触发push的时候改变history.state 的时候加上 base 都能解决

@way-Eric
Copy link

有大佬看看这问题吗,着急

请问,你有解决这个问题吗

我暂时的解决方法修改了主应用中VueRouter的一段源码,具体是 注释掉 /node_modules/vue-router/dist/vue-router.esm-bundler.js 文件中 changeLocation(currentState.current, currentState, true); 这一行

我看了一下,发现是currentState 的地址有问题,因为子应用和主应用共用了history 导致子应用触发后会导致每次触发push 获取currentState 出现问题,然后导致了这个问题,还是隔离不够彻底的问题

或者说在子应用触发push的时候改变history.state 的时候加上 base 都能解决
https://www.cnblogs.com/shapeY/p/17356929.html

@hulong-prong
Copy link

有大佬看看这问题吗,着急

请问,你有解决这个问题吗

我暂时的解决方法修改了主应用中VueRouter的一段源码,具体是 注释掉 /node_modules/vue-router/dist/vue-router.esm-bundler.js 文件中 changeLocation(currentState.current, currentState, true); 这一行

我看了一下,发现是currentState 的地址有问题,因为子应用和主应用共用了history 导致子应用触发后会导致每次触发push 获取currentState 出现问题,然后导致了这个问题,还是隔离不够彻底的问题

或者说在子应用触发push的时候改变history.state 的时候加上 base 都能解决
https://www.cnblogs.com/shapeY/p/17356929.html

不是同一个问题

@huangxu510
Copy link
Author

有大佬看看这问题吗,着急

请问,你有解决这个问题吗

我暂时的解决方法修改了主应用中VueRouter的一段源码,具体是 注释掉 /node_modules/vue-router/dist/vue-router.esm-bundler.js 文件中 changeLocation(currentState.current, currentState, true); 这一行

你的vueRouter 版本是多少

4.0.15

@2317686803
Copy link

2317686803 commented Jul 27, 2023

我遇上了类似的问题。
我的主应用和子应用都是vue3+vue-router4+webpack的,然后是主应用将router传入到了子应用(下文称为parentRouter)。
以下是我碰到的一些问题:
1.子应用通过parentRouter.push方法跳回主应用的home页,然后通过浏览器的“回退”按钮不能正确返回到子应用,会丢
失“activeRule”那一部分。 此问题已通过 https://juejin.cn/post/7184334346583539767 解决。

2. 解决完 子应用\父应用之间相互跳转的问题后,又碰上了子应用通过parentRouter.push跳转其他子应用时,会偶然报错 
   http://xxxxxundefined的问题。此问题已通过  [https://www.cnblogs.com/shapeY/p/17356929.html](url) 解决。

3. 补充:在经过上述处理后,我发现主子应用之间、子子应用之间的跳转都没问题了。但是单个子应用之间的跳转,
   会在点击浏览器的“回退”按钮后出现问题,问题表现为:地址栏错误拼接了两层“activeRule” 导致子应用的路由
   不能正常加载。于是我手动进行了去重处理(不知道原因,自己瞎捣鼓做出来的,目前只是能用,期待大佬们的解惑)

以上修改都是在父应用的router前置拦截器中进行处理的,代码如下:
image

@cjlhll
Copy link

cjlhll commented Sep 1, 2023

楼主解决了吗?

@cjlhll
Copy link

cjlhll commented Sep 1, 2023

有大佬看看这问题吗,着急

请问,你有解决这个问题吗

我暂时的解决方法修改了主应用中VueRouter的一段源码,具体是 注释掉 /node_modules/vue-router/dist/vue-router.esm-bundler.js 文件中 changeLocation(currentState.current, currentState, true); 这一行

我看了一下,发现是currentState 的地址有问题,因为子应用和主应用共用了history 导致子应用触发后会导致每次触发push 获取currentState 出现问题,然后导致了这个问题,还是隔离不够彻底的问题

或者说在子应用触发push的时候改变history.state 的时候加上 base 都能解决

解决了吗?

@2317686803
Copy link

@cjlhll

router.beforeEach(async (to, from) => { let current = window.location.pathname.split('/') if (current[1] === current[2]) { current = current.slice(2) current = current.join('/') current = current.startsWith('/') ? current : '/' + current history.replaceState({back: from.path, current: window.location.pathname}, to.name, current) } else { history.replaceState({back: from.path, current: window.location.pathname}, to.name, '') } })

image

@cjlhll
Copy link

cjlhll commented Sep 1, 2023 via email

@2317686803
Copy link

@cjlhll 这样嘛,那你再去问问其他大佬,我也是找了很多文章后整理的,我在我项目里是勉强能用

@sir-ran
Copy link

sir-ran commented Sep 22, 2023

遇到同样的问题了,主应用中同一个activeRule切换会卸载子应用重复加载。
vue:3.2.47
vue-router:4.1.6

@tianhailiang

This comment was marked as abuse.

@LeonGong
Copy link

LeonGong commented Mar 1, 2024

个人解决办法:主应用 Vue3+VueRouter4 子应用Vue3+VueRouter4 ,可以解决先卸载后加载问题,以及 子应用内部以及子应用间的路由跳转 activeRule重复问题;
//错误路由去重
function checkErrorPath(path) {
if (path.lastIndexOf('/app/') != 0) {
console.log("ERROR")
return path.substring(path.lastIndexOf('/app/'), path.length)
}
return path
}
//判断错误路由
function isErrorPath(path) {
return path.lastIndexOf('/app/') != 0
}
// 基座应用路由守卫
router.beforeEach((to, from, next) => {
//历史记录完善
const fullPath = to.fullPath
history.replaceState({ back: from.path }, to.name , isErrorPath(fullPath)?checkErrorPath(fullPath):'')
if (!window.history.state.current) window.history.state.current = to.fullPath
if (!window.history.state.back) window.history.state.back = from.fullPath

if (to.meta.title) {
document.title = to.meta.title
}
next()
})

@zhangzippo
Copy link

同样的问题

@zhangzippo
Copy link

同样的问题

什么时候能解决啊

@zhangzippo
Copy link

求官方解决下或者有啥绕开的方案吗

@natee
Copy link

natee commented Aug 1, 2024

切主应用时不使用router,直接用a标签跳转可临时解决

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests