wujie icon indicating copy to clipboard operation
wujie copied to clipboard

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

Open jiangdexiao opened this issue 2 years ago • 16 comments

场景:主应用多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 avatar Feb 13 '23 11:02 jiangdexiao

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

xpxs avatar Feb 20 '23 08:02 xpxs

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

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

jiangdexiao avatar Feb 21 '23 03:02 jiangdexiao

最近在做从qiankun迁移到wujie.

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

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

dengBox avatar Feb 22 '23 07:02 dengBox

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

RainManGO avatar Feb 22 '23 08:02 RainManGO

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

jiangdexiao avatar Mar 03 '23 06:03 jiangdexiao

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

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

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

Suo-Ran avatar Mar 13 '23 08:03 Suo-Ran

alive true有效果吗?

jhd2015 avatar Mar 29 '23 03:03 jhd2015

解决方案参考 #516

Alfred-Skyblue avatar Apr 13 '23 02:04 Alfred-Skyblue

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

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

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

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

studeyer avatar May 25 '23 01:05 studeyer

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

santeacher avatar Jun 09 '23 03:06 santeacher

这个地方是这样的,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方法也可以

yiludege avatar Jun 16 '23 03:06 yiludege

最近在做从qiankun迁移到wujie.

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

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

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

alleluya7519 avatar Sep 20 '23 07:09 alleluya7519

这个地方是这样的,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该方法

yuanjianhua avatar Dec 26 '23 02:12 yuanjianhua

这个地方是这样的,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方法也可以

在vue场景下,确实可以在onActivated钩子中去执行startApp方法来解决白屏的问题。但是同样的,这样做本身又失去了keep-alive的意义。

sky124380729 avatar Jul 24 '24 06:07 sky124380729

这个地方是这样的,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方法也可以

该解决方案确实会失去 vue keep-alive 的意义?

该场景 tab1 子应用A pathA,需要切换tab时保留状态(keep-alive) tab2 子应用A pathB, 只能给 tab2 的子应用A起一个不同的名字吗?

heipaoDoctor avatar Nov 01 '24 08:11 heipaoDoctor

name相同,建议不要采用wujie-vue这样

不好意思,求问一下,关键我name不一样也不太行,我很费解 <WujieReact width="100%" height="100%" alive plugins={plugins} key={"iframe" + props.id} name={"iframe" + props.id} url={props.url} sync={!props.url} props={props2} ></WujieReact> 上面的情况,我就直接拿url当name,比如我 /a/xx1 /b/xx1 /b/xx2 /b/xx3 ,这种,我b里面3切到2,会还是3的页面,并且布局错乱了,但是b切到a的就么有问题,求解,用的是React

XzyZachary avatar Apr 23 '25 09:04 XzyZachary