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

vue2作为主应用,使用vue3子应用时,在子应用中切换路由又回退时出现了url自动加上了undefined #2254

Open
carolin-violet opened this issue Aug 30, 2022 · 16 comments

Comments

@carolin-violet
Copy link

What happens?

A clear and concise description of what the bug is.

Mini Showcase Repository(REQUIRED)

Provide a mini GitHub repository which can reproduce the issue.

How To Reproduce

Steps to reproduce the behavior: 1. 2.

Expected behavior 1. 2.

Context

  • qiankun Version:
  • Platform Version:
  • Browser Version:
@Nauxscript
Copy link

Nauxscript commented Sep 9, 2022

我也遇到了类似的情况,在 father 中进入 child 的页面,如 /child/a,然后从 /child/a 通过 child 自己的 router 跳转,即 router.push({path: '/b'}) 跳转到 /child/b 页面,这时在 /child/b 使用 router.back() 方法,会跳转到空白页面,地址栏显示的地址为 /childundefined

child: vue 3.2 / vue-router 4.x
father: vue 2.6.x / qiankun 2.4.8

@zyf540860996
Copy link

我也遇到了类似的情况

@CarsonXin
Copy link

我也有类似的情况,哪怕用浏览器的后退按钮或history.go(-1)也会有这样的问题
父应用:vue@^2.6.11 + vue-router@^3.0.6 + qiankun@^2.4.2
子应用:vue@^3.2.13 + vue-router@^4.0.3

@ripeBoy
Copy link

ripeBoy commented Sep 27, 2022

+1
父应用:vue@2.6.14 + vue-router@3.5.3 + qiankun@2.7.0
子应用:vue@3.2.37 + vue-router@4.1.3

@carolin-violet
Copy link
Author

一开始的注册方法

`import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
{
name: 'react app', // app name registered
entry: '//localhost:7100',
container: '#yourContainer',
activeRule: '/yourActiveRule',
},
{
name: 'vue app',
entry: { scripts: ['//localhost:7100/main.js'] },
container: '#yourContainer2',
activeRule: '/yourActiveRule2',
},
]);

start();`

换了第二种注册方法就不会有undefined问题了,但不知道为什么

`import { loadMicroApp } from 'qiankun';

loadMicroApp({
name: 'app',
entry: '//localhost:7100',
container: '#yourContainer',
});`

@ripeBoy
Copy link

ripeBoy commented Sep 27, 2022

一开始的注册方法

`import { registerMicroApps, start } from 'qiankun';

registerMicroApps([ { name: 'react app', // app name registered entry: '//localhost:7100', container: '#yourContainer', activeRule: '/yourActiveRule', }, { name: 'vue app', entry: { scripts: ['//localhost:7100/main.js'] }, container: '#yourContainer2', activeRule: '/yourActiveRule2', }, ]);

start();`

换了第二种注册方法就不会有undefined问题了,但不知道为什么

`import { loadMicroApp } from 'qiankun';

loadMicroApp({ name: 'app', entry: '//localhost:7100', container: '#yourContainer', });`

vuejs/router#1219

@maikangzhi
Copy link

解决了吗

@Ashuangshuang
Copy link

@Nauxscript @zyf540860996 @CarsonXin @ripeBoy 各位,我现在也遇到这个问题了,请问你们解决了吗?

@maikangzhi
Copy link

@Ashuangshuang

在子应用push 的时候,使用下面其中一种都可以
1,history.pushState(null, '', '#/router-path')
2,主路由 push(‘#/router-path’)
目前我没找到统一的方法,上面两种都可以用来应急,第二种方法是,主应用通过props传它的路由过来。我的做法是在子应用封装了一个push 方法,
export function push(param) {
if (!qiankunWindow.POWERED_BY_QIANKUN) {
router.push(param)
} else {
if (typeof param === 'string') {
param = '#' + param
} else {
param.path = '#' + param.path
}
if (mainRouter) {
mainRouter.push(param)
} else {
history.pushState(null, '', param?.path || param)
}
}
}

@lvchengli
Copy link

@Nauxscript @zyf540860996 @CarsonXin @ripeBoy 各位,我现在也遇到这个问题了,请问你们解决了吗?

@CarsonXin @Nauxscript @zyf540860996 @carolin-violet @ripeBoy @maikangzhi 可以看下我的解决方案。https://github.com/lvchengli/qiankun-demo/tree/feature/fix

// vue2 主应用 + vue3 子应用。在主应用中修改 history,去除子应用的路由前缀
function getPathStr(str) {
  if (str.startsWith('/vue3')) {
    return str.replace('/vue3', '')
  } 
  return str
}

router.afterEach((to, from, next) => {
  console.log(to.fullPath, 'router.afterEach')
  const state = {
    ...history.state,
    current: getPathStr(to.fullPath)
  }
  history.replaceState(state, '', window.location.href)
})

// vue3 主应用 + vue2 子应用。在子应用中修改 history,在router路径前增加子应用的路由前缀
const base = window.__POWERED_BY_QIANKUN__ ? '/vue' : ''

router.afterEach((to, from, next) => {
  const state = {
    ...history.state,
    current: base + to.fullPath
  }
  history.replaceState(state, '', window.location.href)
})

@lsd1
Copy link

lsd1 commented Mar 22, 2023

@lvchengli @carolin-violet @Ashuangshuang @ripeBoy @maikangzhi
可以尝试通过这种方式解决:
子应用使用push方法要注意,不能使用push({ name: 'xxx' })以及push({ path: '带父级的完整路径' })方式去跳转
应该使用push({ path: '子页面路由' }),并且去掉斜杠前面的 '/'
这样就能避免history.back(),或者浏览器后退按钮回退页面是导致路径被追加undefined的问题

eg:
这是一个子应用的路由,里面有多级嵌套
{
path: '/',
name: 'home',
redirect: '/security-manage/dashboard',
children: [{
path: '/security-manage',
name: 'SecurityManage',
component: () => import('@/views/securityManage/Index.vue'),
redirect: '/security-manage/dashboard',
meta: {
title: '安全管理',
},
children: [
{
path: 'dashboard',
name: 'Dashboard',
component: () => import('@/views/securityManage/dashboard/Index.vue')
}
]
}]
}

如果我要跳转到dashboard页面有以下方式都可以完成跳转

  1. router.push({ name: 'Dashboard' })
  2. router.push({ path: '/security-manage/dashboard' })
  3. router.push({ path: 'security-manage/dashboard' }) (比方法二少了一个‘/’)
  4. router.push({ path: 'dashboard' })(比方法三少了一个‘父级路径’)
    使用方法1、2时,如果触发返回,会导致路由后面被追加了个undefined
    方法3、4则不会

@ygcedu
Copy link
Contributor

ygcedu commented Apr 21, 2023

我在vue3作为主应用,react作为子应用时也出现了这个问题,最后发现是vue-router(v4.1.6)的push函数导致的错误,贴一下代码:
image
出现错误的原因就在于子应用的react-router在路由跳转时并不会给currentState.current赋值,导致主应用vue-router这里会是undefined,进而导致如下错误:
image
因此修改也比较简单,直接修改vue-router的源码,如下:
image
详情见我提的一个pr:vuejs/router#1811

@lixioo
Copy link

lixioo commented Aug 1, 2023

楼上找到的这个是根本原因,就是router大版本对currentState的修改方式不同导致的,不好改源码的话,可以自己加一个路由钩子,我这里引了lodash,自己写一个也可以
router.beforeEach((to, from, next) => { if (_.isEmpty(history.state.current)) { _.assign(history.state, { current: from.fullPath }); } next(); });

@apm29
Copy link

apm29 commented Nov 6, 2023

我是主应用vue2.6 + vue-router3.x + webpack, 子应用vue3+vue-router4.x+vite+unplugin-vue-router,同域名下不同子路径,都是hash模式,注册方式是registerMicroApps+start,浏览器回退或者history.back就会出现undefined链接,用了这个方法下可以了

楼上找到的这个是根本原因,就是router大版本对currentState的修改方式不同导致的,不好改源码的话,可以自己加一个路由钩子,我这里引了lodash,自己写一个也可以 router.beforeEach((to, from, next) => { if (_.isEmpty(history.state.current)) { _.assign(history.state, { current: from.fullPath }); } next(); });

@lihua24689
Copy link

楼上找到的这个是根本原因,就是router大版本对currentState的修改方式不同导致的,不好改源码的话,可以自己加一个路由钩子,我这里引了lodash,自己写一个也可以 router.beforeEach((to, from, next) => { if (_.isEmpty(history.state.current)) { _.assign(history.state, { current: from.fullPath }); } next(); });

这个方法下可以了,但是点击浏览器的返回的时候回不到上一个子应用的页面了,多次点击返回就报错了

@Alone-2
Copy link

Alone-2 commented Sep 6, 2024

@Nauxscript @zyf540860996 @CarsonXin @ripeBoy 各位,我现在也遇到这个问题了,请问你们解决了吗?

@CarsonXin @Nauxscript @zyf540860996 @carolin-violet @ripeBoy @maikangzhi 可以看下我的解决方案。https://github.com/lvchengli/qiankun-demo/tree/feature/fix

// vue2 主应用 + vue3 子应用。在主应用中修改 history,去除子应用的路由前缀
function getPathStr(str) {
  if (str.startsWith('/vue3')) {
    return str.replace('/vue3', '')
  } 
  return str
}

router.afterEach((to, from, next) => {
  console.log(to.fullPath, 'router.afterEach')
  const state = {
    ...history.state,
    current: getPathStr(to.fullPath)
  }
  history.replaceState(state, '', window.location.href)
})

// vue3 主应用 + vue2 子应用。在子应用中修改 history,在router路径前增加子应用的路由前缀
const base = window.__POWERED_BY_QIANKUN__ ? '/vue' : ''

router.afterEach((to, from, next) => {
  const state = {
    ...history.state,
    current: base + to.fullPath
  }
  history.replaceState(state, '', window.location.href)
})

vue3 主应用加vue3子应用呢

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