-
Notifications
You must be signed in to change notification settings - Fork 2k
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
[Feature Request] 主应用多页签切换不同子应用的页面状态保持 #361
Comments
我也有同样的需求。不知道用qiankun怎么实现,暂时只能用frame去做了 |
@gaorubin1990 @wisdomG 找到方案了吗? |
同求,一直不敢下手,就是因为这个 |
主应用把标签信息存在了本地存储,然后子应用的container都存在了主应用一个对象里,一个应用一个key,切换路由即切换应用时切换container,子应用的unmonunt函数不销毁子应用。子应用用的keepalive缓存组件状态。子应用通过监听路由变化确定什么时候取消缓存并修改主应用的标签本地缓存信息。这样表面上是实现了,不知道有没有什么性能问题。 |
不行 第一个子应用请求js 域名错误 请求到第二个子应用的域名下了。。。。。 |
|
有没有哪位大佬解决了这个问题啊 |
我解决这个问题了。我的主应用是JQuery(因为一些技术原因暂时保留JQuery),子应用是Vue。Tab切换,会为每个tab页创建一个div容器,我们的子应用页面(Vue)显示在容器中,相应的其他tab页被隐藏,同时切换路由。要实现tab页切换,并保持页面缓存功能,可以换个思路。Vue的keep-alive可以做页面缓存,并且Vue只有一个根实例对象,挂载在一个dom节点上,其内部状态都在实例对象上。因此,在tab切换时,我们可以将dom节点,从一个容器移动到另一个容器,同时随着路由的切换,页面实现了切换,并且keep-alive生效。 |
angular的有思路吗? |
能提供个例子,参考下吗? |
@Liaoct 有例子看下吗?我正好有这个需求 |
我的Vue子应用可以实现Tab切换并保持页面状态,代码如下: let instance = null;
let router = null;
function render() {
// 这里必须要new一个新的路由实例,否则无法响应URL的变化。
router = new VueRouter({
mode: "hash",
base: process.env.BASE_URL,
routes
});
if (
window.__POWERED_BY_QIANKUN__ &&
window.__CACHE_INSTANCE_BY_QIAN_KUN_FOR_VUE__
) {
const cachedInstance = window.__CACHE_INSTANCE_BY_QIAN_KUN_FOR_VUE__;
// 从最初的Vue实例上获得_vnode
const cachedNode =
// (cachedInstance.cachedInstance && cachedInstance.cachedInstance._vnode) ||
cachedInstance._vnode;
// 让当前路由在最初的Vue实例上可用
router.apps.push(...cachedInstance.$router.apps);
// keepAlive可用
cachedNode.data.keepAlive = true;
instance = new Vue({
router,
store,
render: () => cachedNode
});
// 缓存最初的Vue实例
instance.cachedInstance = cachedInstance;
const { path } = router.currentRoute;
const { path: oldPath } = cachedInstance.$router.currentRoute;
// 当前路由和上一次卸载时不一致,则切换至新路由
if (path !== oldPath) {
cachedInstance.$router.push(path);
}
instance.$mount("#app");
} else {
// 正常实例化
instance = new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
}
}
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap() {
console.log("[vue] vue app bootstraped");
}
export async function mount(props) {
console.log("[vue] props from main framework", props);
render(props);
}
export async function unmount() {
console.log("[vue] vue app unmount");
window.__CACHE_INSTANCE_BY_QIAN_KUN_FOR_VUE__ =
instance.cachedInstance || instance;
// 不销毁实例
// instance.$destroy();
// instance = null;
router = null;
} |
子应用实例都挂载在window,那多个子应用不是会被覆盖吗? |
qiankun为每个子应用创建了一个沙箱环境,子应用的window实际上是window.proxy。另外,你也可以不挂载到window,实例也会一直存在的,加载过的子应用不会再次加载。 |
当Router导航未完成就进行路由修正可能会引发路由不匹配的问题。修改方式如下:
|
那这样,父应用要想获取子应用的一下属性,比如路由name来表示window.title,有什么办法吗? |
这个加载过的子应用实例会一致存在,不会被销毁,当有些情况下需要销毁掉子应用实例,重新生成一个全新的,有什么好的方法吗 |
这个条件一般都是来自主应用吧?那就是应用间通信的问题了。如果是子应用控制的,那就是在重新执行mount生命周期时加个控制参数。 |
对于React子应用,我通过react-activation,也实现了页面缓存,暂时还没发现什么问题。Angular不太熟悉,没啥建议了。 |
我的主子应用都是vue的,目前的场景是这样的,主应用是后台多tab的应用,每个tab都加载子应用的不同界面,现在想要达到的效果是,切换tab时缓存住子应用的界面,这点你上面的建议已经能实现,现在最重要的问题是,当我关闭了一个tab,就需要将这个tab的界面从子应用实例中的缓存中移除,不需要再缓存了,好像没有太好的解决办法 |
@Liaoct |
react有什么解决方案么 各位 |
抱歉各位,最近比较忙,手上几个项目跟着的,React缓存还没研究完。上次Vue的方案,还有一点问题,
|
这个方案好像也会有问题,场景是这样到,子应用有两个路由a,b,目前从子应用路由a去到主应用路由后,回到子应用路由a,a切换到路由b会出现一个问题,子应用到内容还是a的。然后我发现这个问题只有子应用真正执行了instance.$destroy()后才不会有这种内容不变的情况。请教一下,要做到可以缓存而且不会出现以上的情况应该怎么处理? |
所以这一块具体是如何解决呢?通过标签页缓存子应用的页面。 |
请问您现在实现了吗? |
您好, 您的实现方案有Demo吗? 十分感谢 |
请问angualr您是如何实现的 |
请问您这边实现了吗? |
如果是react子应用呢? |
react最近刚做完,系统内的缓存使用react-activation,系统外的直接缓存react实例 |
|
只能提供一些伪代码了 export const catchNode = (changeCatch = true) => {
if (changeCatch) needCatch = false;
// node = (document.querySelector('#app') as Node)?.cloneNode(true);
node = document.querySelector('#app');
};
let needCatch;
let node;
export async function bootstrap({ func = {} } = {}) {
// 绑定容器函数
window.func = func;
}
export async function mount() {
console.log('[react] app mount');
needCatch = true;
if (!node) {
runApp(appConfig);
} else {
// 跨系统之后 dom绑定事件不生效,因为是cloneNode。
const oldNode = (document.querySelector('#app') as Node);
oldNode.parentNode?.replaceChild(node, oldNode);
}
}
export async function unmount(props) {
console.log('[react] app unmount');
if (needCatch) catchNode(false);
ReactDOM.unmountComponentAtNode((props?.container || document.querySelector('#app')) as HTMLElement);
}
if (!window.__POWERED_BY_QIANKUN__) {
// 本地测试
bootstrap();
mount();
} |
手动load微前端,然后tabs 直接 缓存微前端的dom,tab关闭手动卸载。 |
Since the issue was labeled with |
少一个给缓存Vue实例添加cachedInstance.$router.apps = [...cachedInstance.catchRoute.apps],离开子应用再跳转回到子应用别的路由会发生页面不刷新的问题,cachedInstance.$router.push方法无效 |
router.onReady(() => { |
请问一下,这样第一次是不会触发activated,生命周期,有什么办法解决吗? |
这样页面会闪的 会去加载css |
大佬能贴完整代码吗 |
我也实现了 主体思想是主应用设置一个全局map,用来存储微应用实例,然后路由拦截,将路由作为key,微应用实例作为value,然后每次新增tab就存起来,移除tab就删掉当前微应用实例并销毁。 |
大佬可不可以贴点代码,我销毁不了离开的页面缓存 |
采用[Liaoct]的方案实现多页签,但是遇到了一个很奇怪的问题,主应用有个路由c,子应用有两个路由a,b,a路由跳转到b,切换到路由c,再回到b页签,再关闭b页签回到a,再从a跳转到b,这个时候会发现this.$router.push({name:'b',params:{'a':'1'}})的params丢失了,获取不到,从a跳转去其他路由的params都处于丢失的状态,大佬们,有遇到这个问题吗?Vue版本是2 |
let router = null; //挂载实例
} //判断当前运行环境是独立运行的还是在父应用里面进行运行,配置全局的公共资源路径 export async function mount(props) { export async function unmount() {
} }
|
看了您的代码,得出您是这样实现的:
参照下面的评论里我实现了vue2子应用unmount也能保活,但是vue3的无法保活 |
Background
想要主应用负责导航及页面页签切换,切换页签,即切换不同子应用的页面时,container不重新覆盖。看了下singular: false适用于一个路由页面组合展示的不同子应用界面场景?能否指导一下该需求的实现思路,非常感谢
Proposal
Describe the solution you'd like, better to provide some pseudo code.
Additional context
Add any other context or screenshots about the feature request here.
The text was updated successfully, but these errors were encountered: