背景

微前端 qiankun 有两种运作模式:
1、使用 registerMicroApps + start,这是挂自动档,路由改变,重新load子应用。
2、使用 loadMicroApp,每次路由匹配上,手动load子应用。

以上这两点 官方文档 也有详细的 API 说明。

registerMicroApps + start

API

注册微应用的基础配置信息。当浏览器 url 发生变化时,会自动检查每一个微应用注册的 activeRule 规则,符合规则的应用将会被自动激活。

import { registerMicroApps } from 'qiankun';const apps = [{// 微应用的名称,微应用之间必须确保唯一。name: 'app1',// 微应用的入口。entry: '//localhost:8080',// 微应用的容器节点的选择器或者 Element 实例。container: '#container',// 浏览器 url 发生变化会调用 activeRule 里的规则activeRule: '/react',// 主应用需要传递给微应用的数据。props: {name: 'kuitos',},},
]registerMicroApps(apps, {// 加载子应用前,可以用来加载进度条beforeLoad: (app) => console.log('before load', app.name),beforeMount: (app) => console.log('before load', app.name),// 加载子应用后,可以用来关闭进度条afterMount: (app) => console.log('after load', app.name),beforeUnmount: [(app) => console.log('before mount', app.name)],afterUnmount: [(app) => console.log('before mount', app.name)],},
);
import { start } from 'qiankun';
const options = {// 是否预加载prefetch: true,// 是否开启沙箱样式隔离sandbox: true,// 是否为单实例场景,单实例指的是同一时间只会渲染一个微应用。默认为 true。singular: true
}
start(options)

singular: false 的使用场景:
例如:有一个父页面,左边是菜单列表,右边上半部分是子项目A的展示区域,右边下半部分是子项目B的展示区域。而且A、B是同时呈现在父页面中的。
办法1:registerMicroApps 注册时两个子应用使用相同的activeRule,但使用不同的 container,并且设置 singular 值为 false
办法2:直接使用两次 loadMicroApp ,使用不同的 container 分别加载两个子应用

注意事项

自动档下,是这样运作的:
1、首次load应用,创建子应用实例,渲染。
2、当切到其他子应用后切回,会重新创建新的子应用实例并渲染。之前的子应用实例 qiankun 直接不要了,即使你没有手动销毁实例。

所以说,采用这种模式的话一定要在子应用暴露的unmount钩子里手动销毁实例,不然就内存泄漏了。

export async function unmount() {instance.$destroy();instance.$el.innerHTML = '';instance = null;router = null;
}

所以在 qiankun 中,如果子应用使用 keep-alive 来保存状态,那么从子应用1切到子应用2,再切回子应用1,是不会保存状态的,因为整个子应用实例都被弃之不用了造成了重新加载。

loadMicroApp

通常这种场景下微应用是一个不带路由的可独立运行的业务组件,所以可以看到下面的 api 中没有路由相关的。

API

手动加载一个微应用。

如果需要能支持主应用手动 update 微应用,需要微应用 entry 再多导出一个 update 钩子:

微应用:

export async function mount(props) {renderApp(props);
}// 微应用中增加 update 钩子以便主应用手动更新微应用
export async function update(props) {renderPatch(props);
}

主应用:

import { loadMicroApp } from 'qiankun';
import React from 'react';const app = {// 微应用的名称,微应用之间必须确保唯一。name: 'app1',// 微应用的入口。entry: '//localhost:8080',// 微应用的容器节点的选择器或者 Element 实例。container: '#container',// 主应用需要传递给微应用的数据。props: {name: 'kuitos',},
}class App extends React.Component {containerRef = React.createRef();microApp = null;componentDidMount() {// 返回值为微应用的示例,有对应的一些方法可以调用// mount、unmount、update、getStatus、loadPromise、bootstrapPromise、mountPromise、unmountPromisethis.microApp = loadMicroApp(app, {// 是否开启沙箱样式隔离sandbox: true,// 是否为单实例场景,单实例指的是同一时间只会渲染一个微应用。默认为 false。singular: false});}componentWillUnmount() {this.microApp.unmount();}componentDidUpdate() {this.microApp.update({ name: 'kuitos' });}render() {return <div ref={this.containerRef}></div>;}
}

注意事项

对于自动挡模式下会丢失应用的问题,loadMicroApp 模式下不会有,loadMicroApp 的策略是每个子应用都有一个唯一的实例ID,reload时会复用之前的实例。剔除我们不关心的细节,抽象出来的代码是这样的:

https://codesandbox.io/s/great-leakey-rv03i?file=/src/index.js

当然这个例子中没有路由切换,所以可以没有keep-alive也成功存住状态了。

看这段代码要关注的是ReactDOM.render的行为,现在是往wrapper0里render了两次App0,这种case下App0的状态是保留了首次的。

但是如果往wrapper里render null或者其他App之后再次render App0,那么App0第一次渲染时的状态是不会被保留的。

而我阅读了qiankun的源码,得出的结论是qiankun中的行为就是我例子中这样的,所以App0的状态可以被保留。

那么有人会问,子应用很可能是Vue的啊,那么情况是什么样的呢?如果有这个疑问,说明可能这对你而言是一个很好的动手机会,真实的用qiankun作为基座,切换子应用时keep-alive的代码已经在这个仓库了,你可以自行增加一个Vue子应用

下面总结下最简实现子应用keep-alive的操作,其实只需两步:

1、基座中监听路由变化,变化后通过 loadMicroApp 加载对应子应用。
2、子应用中 keep-alive。

React中可以这样来keep-alive:

import CacheRoute, {CacheSwitch} from 'react-router-cache-route';// 在路由配置处使用CacheRoute缓存希望keep-alive的组件,注意when要配置为always
<CacheSwitch><CacheRoute when="always" exact path="/list" component={List} /><CacheRoute when="always" exact path="/item" component={Item} />
</CacheSwitch>

更进一步:
我们的基座中展示子应用和浏览器展示标签页是的表现是一样的,但是最简方案下,关闭标签页也没有卸载子应用实例,仍然占据着内存,并且下次重新打开也不是全新的子应用,这理论上是不符合预期的行为。

所以我们的解决方案是:
1、在子应用暴露的 unmount 钩子中写好卸载子应用的逻辑,如调用ReactDOM.unmountComponentAtNode
2、在基座中,关闭标签页时,手动调用app的unmount钩子

总结

一般情况下使用自动挡就可以了,如果微应用是一个不带路由的可独立运行的业务组件,可以用手动挡来加载这个子应用。

参考资料

https://github.com/chenbj5515/qiankun-keep-alive

微前端:qiankun的两种运作模式相关推荐

  1. 前端路由的两种模式:hashhistory

    前端路由的两种模式:hash和history 1.hash hash模式是通过onhashchange事件,监听url的修改优点:兼容性比较高,可以直接在项目部署上线时使用缺点:url中带#号,不美观 ...

  2. 基于微前端qiankun的多页签缓存方案实践

    作者:vivo 互联网前端团队- Tang Xiao 本文梳理了基于阿里开源微前端框架qiankun,实现多页签及子应用缓存的方案,同时还类比了多个不同方案之间的区别及优劣势,为使用微前端进行多页签开 ...

  3. 广州蓝景分享—目前微前端架构的几种技术选型,你了解吗?

    各位编程的小伙伴,今天广州蓝景继续跟大家分享前端技术相关文章:微前端架构的几种技术选型,你了解吗?随着SPA大规模的应用,紧接着就带来一个新问题:一个规模化应用需要拆分. 一方面功能快速增加导致打包时 ...

  4. qiankun 传统项目配置_微前端 qiankun 项目实践

    原标题:微前端 qiankun 项目实践 作者:zxh1307 https://juejin.im/post/5ea55417e51d4546e347fda9 导语 最近在做微前端的项目 , 过程中真 ...

  5. c语言实现路由功能,前端路由的两种实现方式,内附详细代码

    一.前端路由介绍 前端路由主要应用在SPA(单页面开发)项目中.在无刷新的情况下,根据不同的URL来显示不同的组件或者内容. 前端路由的实现原理 : hash值 + onhashchange事件 hi ...

  6. 一步一步学FRDM-KE02Z(一):IAR调试平台搭建以及OpenSDA两种工作模式设置

    摘要:FRDM-KE02Z是飞思卡尔公司较为新的微控制器,学习和开发资料较少.从本篇开始会陆续介绍其相关的开发流程,并完成一个小型的工程项目.这是本系列博客的第一篇,主要介绍开发环境IAR for A ...

  7. WordPressX主题插件交易平台的两种变现模式

    加入WordPressX主题插件交易平台有以下两种变现模式 一.自主开发模式 创作者所发布的所有作品除减去售价的10%作为平台服务费之外,创作者全权享有售价90%的销售收益 并且极有可能获得作品售出后 ...

  8. 模糊匹配 读音_onenote搜索机制详解②:两种搜索模式,模糊与精确匹配

    先从纯文本搜索讲起,这是最基本也是最重要的. 从这篇开始,以及接下来连续几篇文章,都会介绍搜索的基础功能.注意,这几篇文章中谈论的都是基本的.正常的搜索功能,暂时不考虑Bug等因素. 在很多软件(例如 ...

  9. 网页html文档头部声明的两种常用模式

    Html文档头部声明的两种常用模式 第一种,XHTML1.0严格模式,对很多废除的标签不支持,书写要严格遵守W3C的要求,是找虐的好方法: <!DOCTYPE html PUBLIC " ...

最新文章

  1. JS设计模式-观察者模式
  2. PostgreSQL SQL 语言:并行查询
  3. c2064 项不会计算为接受0个参数的函数_【JS必知必会】高阶函数详解与实战
  4. A/B测试:概念 ≠ 执行
  5. Https 与 SSl证书 概要
  6. 计算机基础知识:原码、反码、补码
  7. 去掉登陆下的“扫一扫,访问微社区
  8. getsockopt和setsockopt函数
  9. 数据千万条,安全第一条
  10. 设计模式笔记十九:备忘录模式
  11. call stack是什么错误_Go语言(golang)的错误(error)处理的推荐方案
  12. linux命令——scp 两台linux机器间文件或目录传输
  13. Flutter学习 — 设计基础
  14. (IoT物联网)天线的设计步骤 - 完整收藏版
  15. 三角形外接圆圆心 算法 删改版
  16. 怎么设置电脑防火墙ping启用_如何通过windows防火墙启用和禁用ping命令
  17. CommonAPI新版本配置
  18. 液晶显示屏简介以及与CRT显示屏的对比
  19. 阿里网盘rar再打包分享工具
  20. ASP.NET EXCEL导入,身份证、手机号长度校验数据校验

热门文章

  1. 天天狼人杀改密码_是时候杀了密码了吗?
  2. linux - apollo系统
  3. 被hao123劫持后该如何解决
  4. 深度测评各大集成灶品牌的优缺点(解读集成灶好处和坏处)
  5. xftp传输文件失败的解决方法
  6. python怎么退出游戏_当游戏结束条件不满足时,如何退出游戏?
  7. php 断点调试 PHPStorm Xdebug helper
  8. jQuery入口函数
  9. 我的k8s随笔:Kubernetes部署-问题篇
  10. MUV LUV UNLIMITED(树上博弈 奇偶性)