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

主应用多Tab页签,无论哪种模式下,如果组件name一致,就会导致切换tab后加载的子应用页面无法正常挂载活激活 #391

Open
jiangdexiao opened this issue Feb 13, 2023 · 13 comments

Comments

@jiangdexiao
Copy link

jiangdexiao commented Feb 13, 2023

场景:主应用多Tab页签,无论哪种模式下,主应用如果使用了Keep-Alive 组件的情况下,如果组件name一致,就会导致切换tab后加载的子应用页面无法正常挂载活激活

此现象在三种模式下都会出现,

  1. 出现原因就是如果同一个子应用(注意是同一个子应用不同页面)传递给WuJie组件的name一致,如果同一个子应用不同页面都传递不同name就可以显示,
  2. 如果是不同子应用,切换A应用到B应用,在B应用没有页面被打开前,第一次打开B页面正常,此后切换回A应用其他页面或者B应用其他页面都无法正常加载

复现步骤
1.从菜单打开A菜单正常新增一个tab,可以正常加载出来子应用app1的test1页面
4.从菜单在打开B菜单继续新增一个tab,依然可以正常加载出来子应用app1的test2页面,此时从控制台可以看到,test1被卸载了,接着挂载test2
5.切换tab到test1,空白,没有加载出来,从控制台可以看到,此时卸载了test2,但是没有重新挂载test1
6.保活模式下:打开page1菜单,新增tab1,正常加载子应用页面1,在打开page2菜单,新增tab2,此时tab2页面里显示的还是子应用页面1,没有正确加载子应用页面2,控制台可以看到主应用已经通知到子应用做路由跳转了

错误截图
gae0b7b9

wujiebaohuo1
wujiebaohuo2

主应用代码:

<WujieVue width="100%" height="100%" :name="microName" :url="microUrl" :props="{microName: microName,description: '描述'}" :sync="false" :alive="false" :beforeLoad="beforeLoad" :beforeMount="beforeMount" :afterMount="afterMount" :beforeUnmount="beforeUnmount" :afterUnmount="afterUnmount" :activated="activated" :deactivated="deactivated" :loadError="loadError" ></WujieVue>

子应用代码:
`const router = new VueRouter({
mode: 'history',
routes,
})

if (window.POWERED_BY_WUJIE) {
let instance;
window.__WUJIE_MOUNT = () => {
console.log('__WUJIE_MOUNT')
instance = new Vue({ router, render: (h) => h(App) }).$mount("#app");
};
window.__WUJIE_UNMOUNT = () => {
console.log('__WUJIE_UNMOUNT')
instance.$destroy();
};
} else {
new Vue({ router, render: (h) => h(App) }).$mount("#app");
}`

关于无界三种模式思考:
1.保活模式:整个应用实例被保存,关闭页面重新打开,上一次操作的数据依然存在,然而,这种模式适合什么场景,多实例激活场景?实际情况下,肯定是希望关闭页面重新打开,是恢复到页面原位状态,当然,可以说需要恢复到原来状态可以使用重建模式?可是重建模式每次都要做销毁,重建的动作,对性能目前看起来是有比较明显的影响,体验明显不足。
2.单例模式:无界这里的单例模式文档实际没有说明比较清楚,是指多个子应用只允许一个应用当前激活嘛?
3.重建模式,按上面情况,多tab时候,是要存在多实例激活的,也就是多tab只能使用重建模式?

4.个人思考:从应用角度看,其实可以理解只有只有两种模式,一种就是单例激活,一种就是多例激活,无界对比qiankun,无疑qiankun很明确,单例和多实例两种模式。所以wujie这里的保活模式和重建模式 是为什么场景设置的?这个场景看起来很模糊,如果保活模式是为了多实例激活场景而存在,那重建模式是否没有必要(如果可以不频繁创建和销毁,肯定没有人希望用重建,首选是保活),只要解决保活模式在上述中的场景不足,因为关闭页面重新打开从哪种角度看都是应该恢复原来状态(实际情况下是希望缓存应用实例,而非连状态全部都缓存),而如果保活模式不是为了多实例场景,那么多实例场景要用什么模式呢,目前看起来有三个模式,但是从应用角度上看,好像哪个模式都不适合。

建议:

  1. 运行模式的文档应该更加细致一些,目前看起来比较粗糙,含糊
  2. 无界组件内部脚本错误没有提供开发模式下可打印出日志么,目前即使页面加载失败或者空白,都无法看到具体错误是什么,无疑是个黑盒,对于调试比较不利
@jiangdexiao jiangdexiao changed the title 主应用多Tab页签,单例模式,组件name也一致,切换tab后再切换回来页面没有重新挂载空白了 主应用多Tab页签,无论哪种模式下,如果组件name一致,就会导致切换tab后加载的子应用页面无法正常挂载活激活 Feb 14, 2023
@xpxs
Copy link

xpxs commented Feb 20, 2023

我这边的解决方案是给name后面加上时间戳,不够优雅,但是可以解决多页签切换的问题

@jiangdexiao
Copy link
Author

我这边的解决方案是给name后面加上时间戳,不够优雅,但是可以解决多页签切换的问题

那就不是共享一个实例了,keep-alive 加 上include属性后 可以,你试试

@dengBox
Copy link
Contributor

dengBox commented Feb 22, 2023

最近在做从qiankun迁移到wujie.

切换的原因是,qiankun采用了eval去执行js模拟沙箱,导致性能会有问题并且目前css的沙箱也有问题。
对于多页签现在的做法有以下两种思路:
子系统均不采用sync,使用bus同步路由信息。

  1. 使用alive模式,因为都是独立的沙箱也不存在有污染的问题,最多是一些业务代码,诸如定时器等等有性能问题。
  2. 采用单例模式,子系统在销毁时缓存vue 、react的实例,然后调用销毁方法。这种方向会极大的减轻内存,实现也比较复杂。

@RainManGO
Copy link

用Tabs 页签保活无界子应用。 页面缓存利用Tab s 显示隐藏实现,这也是react 不做keppalive dan给的方案。

@jiangdexiao
Copy link
Author

经过实践,总体来看,复杂应用还是不要用这个,在稳定性上面有很大缺陷,如果你的应用场景比较简单,那问题其实不大,已经发现了很多的奇形怪状的问题出现,而且对于开发者来说是个黑盒,内置error钩子都没有任何报错,跟外部一些组件存在耦合,一些场景下,生命周期无法触发,然后没有捕获任何错误。调试难度比较大

@Suo-Ran
Copy link

Suo-Ran commented Mar 13, 2023

我这边的解决方案是给name后面加上时间戳,不够优雅,但是可以解决多页签切换的问题

那就不是共享一个实例了,keep-alive 加 上include属性后 可以,你试试

您好,您能分享下demo吗,我通过keep-alive 加 上include属性后也无法解决,还是通过时间戳才行,您是怎么解决的,具体代码可以分享下嘛

@jhd2015
Copy link

jhd2015 commented Mar 29, 2023

alive true有效果吗?

@Alfred-Skyblue
Copy link
Contributor

解决方案参考 #516

@studeyer
Copy link

我这边的解决方法是给名字后面加上时间,不够优雅,但是可以解决多页签换的问题

那就不是共享一个实例了,keep-alive加上include属性后可以,你试试

您好,您能分享下demo吗,我通过keep-alive加上include属性后也无法解决,还是通过时间间隔才行,您是怎么解决的,具体代码可以分享下嘛

您好 这个您整出来了嘛,参考方案确实没看懂 不知道是怎么回事

@santeacher
Copy link

@xpxs 打扰下,使用keep-alive, 如果想多标签切换同时还保留子项目页面的内容,应该如何配置,研究尝试没有找到合适的方法,如果您有好的办法麻烦指导下,非常感谢。

@yiludege
Copy link
Collaborator

这个地方是这样的,name相同的话,切换到新的tab,原来的tab上wujie-vue就销毁了,如果tab有缓存意味切换回来tab的中组件wujie-vue组件不会重新渲染,看到页面就是空白,如果想要name相同,建议不要采用wujie-vue这样的框架封装,每次切换tab的时候 调用 startApp({name: 'xxx',el: 'xxx'}),主动渲染

当然 wujie-vue 也有 startApp 的方法,通过 ref 拿到组件实例,然后每次切换tab都调用对应 wujie-vue里面的 startApp方法也可以

@alleluya-young
Copy link

最近在做从qiankun迁移到wujie.

切换的原因是,qiankun采用了eval去执行js模拟沙箱,导致性能会有问题并且目前css的沙箱也有问题。
对于多页签现在的做法有以下两种思路:
子系统均不采用sync,使用bus同步路由信息。

  1. 使用alive模式,因为都是独立的沙箱也不存在有污染的问题,最多是一些业务代码,诸如定时器等等有性能问题。
  2. 采用单例模式,子系统在销毁时缓存vue 、react的实例,然后调用销毁方法。这种方向会极大的减轻内存,实现也比较复杂。

你好 请问qiankun迁移到wujie 有什么需要注意的地方吗 有相关介绍的文章或者参考的东西么?

@yuanjianhua
Copy link

这个地方是这样的,name相同的话,切换到新的tab,原来的tab上wujie-vue就销毁了,如果tab有缓存意味切换回来tab的中组件wujie-vue组件不会重新渲染,看到页面就是空白,如果想要name相同,建议不要采用wujie-vue这样的框架封装,每次切换tab的时候 调用 startApp({name: 'xxx',el: 'xxx'}),主动渲染

当然 wujie-vue 也有 startApp 的方法,通过 ref 拿到组件实例,然后每次切换tab都调用对应 wujie-vue里面的 startApp方法也可以

看了下,好像没有startApp该方法

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