文章概述
实践微前端-angular+qiankun - 从 0 到 1 篇
实践微前端-angular+qiankun - 应用间通信篇
实践微前端-angular+qiankun - 项目Nginx发布已经在紧张编写测试(欢迎回访)
github传送门
angular+qiankun+single-spa 欢迎探讨技术问题
引言
大家好~
本文是基于 qiankun + single-spa 的微前端最佳实践系列文章之 应用间通信篇,默认你是读过 从 0 到 1 篇
,如果没有可以点击上面的文章链接。
本篇本文将分享如何使用 qiankun + single-spa 如何在主应用或者子应用中 发送
或者 订阅
qiankun的 globalState
全局数据获取。
Actions
通信
qiankun
内部提供了 initGlobalState
方法用于注册 MicroAppStateActions
实例用于通信,该实例有三个方法,分别是:
setGlobalState
:设置globalState
- 设置新的值时,内部将执行浅检查
,如果检查到globalState
发生改变则触发通知,通知到所有的观察者
函数。onGlobalStateChange
:注册观察者
函数 - 响应globalState
变化,在globalState
发生改变时触发该观察者
函数。offGlobalStateChange
:取消观察者
函数 - 该实例不再响应globalState
变化。
我们来画一张图来帮助大家理解(见下图)
我们从上图可以看出,我们可以先注册 观察者
到观察者池中,然后通过修改 globalState
可以触发所有的 观察者
函数,从而达到组件间通信的效果。
实战教程
我们以 github上面实战为例(上面有传送门)
(案例是以 Angular10
为基座的主应用,接入 Angular10
子应用) 为例,来介绍一下如何使用 qiankun
完成应用间的通信功能。
建议 clone 实战案例 - 拉取代码到本地,运行项目查看实际效果。
主应用的任务
首先,我们在主应用中注册一个 MicroAppStateActions 实例并导出,代码实现如下:
import { MicroAppStateActions, initGlobalState } from 'qiankun'
// 初始化 state
/** 在当前应用监听全局状态,有变更触发 callback,fireImmediately = true 立即触发 callback */
export const Actions: MicroAppStateActions = initGlobalState({
micro: '主引用加载完成!',
})
在注册 MicroAppStateActions 实例后,在shared中使用该actions.service.ts,中我们通过service
服务封装微服务的 观察者
和 发布函数
,实现如下:
@Injectable({
providedIn: 'root',
})
export class ActionsService {
private actions: MicroAppStateActions = Actions
constructor() {}
/** 在当前应用监听全局状态,有变更触发 callback,fireImmediately = true 立即触发 callback */
onGlobalStateChange() {
return this.actions.onGlobalStateChange
}
/** 按一级属性设置全局状态,微应用中只能修改已存在的一级属性 */
setGlobalState(data) {
this.actions.setGlobalState(data)
}
}
然后再 app.module.ts
中注册 actions.service.ts
该服务,就可以实现全局调用,实现如下:
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
BrowserAnimationsModule,
IconsProviderModule,
FormsModule,
HttpClientModule,
RouterModule,
RoutersModule,
],
// ActionsService 放在 providers中
providers: [ActionsService, { provide: NZ_I18N, useValue: en_US }],
bootstrap: [AppComponent],
})
export class AppModule {}
}
接下来需要在主应用中使用qiankun微服务来加载 子应用
和 使用 观察者
和 发布函数
来观察,实现如下:
export class WelcomeComponent implements OnInit {
microApp
@ViewChild('mango_iview')
containerRef: ElementRef
mangoState
count = 1
constructor(private actions: ActionsService) {}
ngOnInit() {
this.actions.onGlobalStateChange()((state, prev) => {
this.mangoState = state
console.warn('主应用获取- state--->' + this.mangoState)
console.warn('主应用获取- prev--->' + prev)
})
}
ngAfterViewInit(): void {
// 手动加载子应用
this.microApp = loadMicroApp({
name: 'mango-iview',
entry: '//localhost:4300',
container: this.containerRef.nativeElement,
})
}
/**
* 发布函数
*/
setGlobal(data) {
this.actions.setGlobalState(data)
this.count++
}
}
html 非常简洁
<button nz-button nzType="primary" (click)="setGlobal({micro:'我是主应用',id:count})">我要发送主应用变量</button>
<div #mango_iview id="mango-iview"></div>
子应用的任务
我们已经完成了主应用的 发布函数
,将 data
信息记录在了 globalState
中。现在,我们进入子应用,使用 data
获取用户信息并展示在页面中,实现如下。
import {
singleSpaPropsSubject,
SingleSpaProps,
} from '../single-spa/single-spa-props';
@Component({
selector: 'iview-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.less'],
})
export class AppComponent {
title = 'mango-iview';
state;
subscription: Subscription;
singleSpaProps: SingleSpaProps;
count = 0;
ngOnInit() {
this.subscription = singleSpaPropsSubject.subscribe(async (props) => {
props['onGlobalStateChange']((state, prev) => {
// state: 变更后的状态; prev 变更前的状态
this.state = state;
console.warn('iview的接收值- state--->' + JSON.stringify(state));
console.warn('iview的接收值- prev--->' + JSON.stringify(prev));
this.countAdd();
});
console.warn('iview的初始化的接收父组件的value---->' + props);
this.singleSpaProps = props;
});
}
// 展示子应用接受值的数量
async countAdd() {
this.count++;
console.log(this.count);
}
// 子应用 发布函数
setGlobalState(data) {
data++;
this.singleSpaProps['setGlobalState']({
micro: '我是子应用iview',
id: data,
});
}
}
html 还是简洁
<div>
<hr />
<h1>Iview 子应用</h1>
<h1 (click)="countAdd()">console</h1>
<button (click)="setGlobalState(count)">子应用发来贺电</button>
<div>state:{{ state | json }}</div>
<div>count:{{ count }}</div>
</div>
最后,我们来看看实际效果。我们从主应用 发送 data数据 子应用接收数据渲染,并可以发送data数据到主应用形成闭环。效果啦!(见下图)
小结
到这里,qiankun 基础通信 就完成了!
我们在主应用中实现了观察者
,和 发布函数
发布的数据 存入 globalState 状态池中。在进入子应用时,我们使用 singleSpaPropsSubject
获取 singleSpaProps
对象和观察者
,再使用 singleSpaProps
发布函数通知主应用,完成页面数据渲染!
小纠结(被技术问题困扰欢迎探讨)
ps: 为什么这么久没更新因为发现了一个小问题 。 就是主应用更新
globalState
数据状态,子应用的值接收到了也console
出来了,但是页面显示不出来。必须要在页面(html)
上点一下console的按钮
在调用ts里面调用console(){console.log(this.count);}
的方法才在子应用页面显示内容(代码例子也有)。
有点怀疑是子应用的隔离或者没有使用的问题也不一定。。。
最后一件事
如果您已经看到这里了,希望您还是点个赞
再走吧~
您的点赞是对作者的最大鼓励,也可以让更多人看到本篇文章!