qiankun 内实现应用通讯的三种方式(props、initGlobalState、socket.io)
qiankun 内实现应用通讯的三种方式(props、initGlobalState、socket.io)
目录
2.1.3 返回(返回 MicroAppStateActions 实例)
2.2 initGlobalState(state) 通信原理
3.1.1 注册 MicroAppStateActions 实例
3.1.2 使用 MicroAppStateActions 实例
5.2 使用 qiankun 提供的 API initGlobalState 进行通信
1. props
1.1 主应用中定义 props
在主应用中,注册微应用的基础配置信息时,定义 props ,编写需要传递给微应用的信息
如下代码所示,props 中添加了给微应用传递的参数
window.microApp = [
{
name: 'micro-app', // 唯一值。建议和 package.json 中的 name 一致
entries: {
dev: '//localhost:8081/', // 开发环境
product: '//xxx.xxx.x.xxx:8104/vue3-backstage-micro-app/', // 线上
},
container: '#micro-app', // 容器 ID
activeRule: getActiveRule('#/vue'), // 激活路径
props: {
id: 'props 传值方式'
},
},
];
1.2 微应用中获取 props
微应用在 qiankun 框架的 mount 生命周期里,可以获取 props
由于在 mount 生命周期里,调用了 render() 函数,所以在 render 中要定义接收 props 的参数
function render(props?: any) {
console.log(props?.id);
}
...
// 生命周期
....
export async function mount(props): Promise<void> {
render(props);
}
...
打印结果:
2. initGlobalState(state)
2.1 基本使用说明
initGlobalState() 是 qiankun 提供的通信 API
API 说明 - qiankunhttps://qiankun.umijs.org/zh/api#initglobalstatestate
2.1.1 参数
state - Record<string, any> - 必选
2.1.2 用法
定义全局状态,并返回通信方法,建议在主应用使用,微应用通过 props 获取通信方法
2.1.3 返回(返回 MicroAppStateActions 实例)
在当前应用监听全局状态,有变更触发 callback,fireImmediately = true 立即触发 callback
onGlobalStateChange:
(callback: OnGlobalStateChangeCallback, fireImmediately?: boolean) => void
按一级属性设置全局状态,微应用中只能修改已存在的一级属性
setGlobalState:
(state: Record<string, any>) => boolean
移除当前应用的状态监听,微应用 umount 时会默认调用
offGlobalStateChange:
() => boolean
2.1.4 官方示例
主应用:
import { initGlobalState, MicroAppStateActions } from 'qiankun';
// 初始化 state
const actions: MicroAppStateActions = initGlobalState(state);
actions.onGlobalStateChange((state, prev) => {
// state: 变更后的状态; prev 变更前的状态
console.log(state, prev);
});
actions.setGlobalState(state);
actions.offGlobalStateChange();
微应用:
// 从生命周期 mount 中获取通信方法,使用方式和 master 一致
export function mount(props) {
props.onGlobalStateChange((state, prev) => {
// state: 变更后的状态; prev 变更前的状态
console.log(state, prev);
});
props.setGlobalState(state);
}
2.2 initGlobalState(state) 通信原理
qiankun 内部提供了 initGlobalState 方法,用于注册 MicroAppStateActions 实例
MicroAppStateActions 实例包含了三个用于应用通信的方法:
- onGlobalStateChange:注册 观察者 函数 - 响应 globalState 变化,在 globalState 发生改变时触发该 观察者 函数。
- setGlobalState:设置 globalState - 设置新的值时,内部将执行 浅检查,如果检查到 globalState 发生改变则触发通知,通知到所有的 观察者 函数【深度监听的】
- offGlobalStateChange:取消 观察者 函数 - 该实例不再响应 globalState 变化
综上所述:
- 每个应用都可以注册 观察者 到观察者池中
- 每个应用都可通过修改 globalState,触发所有的 观察者 函数,实现应用通信
3. 实战
场景:主应用登录后,需要给各个微应用传递登录后获得的 token
3.1 主应用
3.1.1 注册 MicroAppStateActions 实例
import {
registerMicroApps,
start,
initGlobalState
MicroAppStateActions,
} from 'qiankun';
....
// 注册微应用通信示例
const initialState = {};
const actions: MicroAppStateActions = initGlobalState(initialState);
export {
start, // 导出 qiankun 的启动函数
actions, // 导出通信示例
}
3.1.2 使用 MicroAppStateActions 实例
在登录页面中,使用 3.1.1 定义的 MicroAppStateActions 实例:
- 注册 观察者 函数:actions.onGlobalStateChange((state, prevState) => { ... })
- 触发 观察者 函数:actions.setGlobalState({ ... })【深度监听的】
<template>
<button @click="handleLogin">登录</button>
</template>
<script lang="ts">
import { defineComponent, onMounted } from 'vue';
import { actions } from '@/hooks/micro-app';
export default defineComponent({
name: 'Login',
setup() {
onMounted(() => {
/**
* 注册一个观察者函数
* @param state 变更后的状态
* @param prevState: 变更前的状态
*/
actions.onGlobalStateChange((state, prevState) => {
console.log("主应用观察者:token 改变前的值为 ", prevState.token);
console.log("主应用观察者:token 改变后的值为 ", state.token);
});
});
/**
* 点击登录
*/
const handleLogin = () => {
// 登录成功后,设置 token
actions.setGlobalState({ token: new Date() });
...
};
return {
handleLogin,
};
}
})
</script>
3.2 微应用
在 3.1 中,主应用内获取的 token 已经被记录在了 globalState 中,接下来要在微应用中获取它
3.2.1 在 main.ts 中接收参数
function render(props?: any) {
if (props) {
/**
* 注册一个观察者函数
* @param state 变更后的状态
* @param prevState: 变更前的状态
*/
props.onGlobalStateChange(
(state: { token: any }, prevState: { token: any }) => {
// state: 变更后的状态; prevState: 变更前的状态
console.log("微应用观察者:token 改变前的值为 ", prevState.token);
console.log("微应用观察者:token 改变后的值为 ", state.token);
}
);
}
}
// 生命周期
export async function mount(props): Promise<void> {
render(props);
}
3.2.2 在实际业务相关的 .vue 文件中使用参数
第一步:新建 /hooks/actions.ts,存放全局使用通信的实例方法
function emptyAction(...args: any[]) {
// 警告:提示当前使用的是空 Action
console.warn("Current execute action is empty!");
}
class Actions {
// 默认值为空 Action
actions = {
onGlobalStateChange: emptyAction,
setGlobalState: emptyAction,
};
/**
* 设置 actions
*/
setActions(actions: {
onGlobalStateChange: () => void;
setGlobalState: () => void;
}) {
this.actions = actions;
}
/**
* 映射
*/
onGlobalStateChange(...args: any[]) {
return this.actions.onGlobalStateChange(...args);
}
/**
* 映射
*/
setGlobalState(...args: any[]) {
return this.actions.setGlobalState(...args);
}
}
const actions = new Actions();
export default actions;
第二步:在入口文件引入 /hooks/actions.ts ,并为其注入真实 Actions
function render(props?:any) {
if (props) {
// 注入 actions 实例
actions.setActions(props);
}
...
}
// 生命周期
export async function mount(props): Promise<void> {
render(props);
}
第三步:在需要用到通信参数的 vue 页面里,引入 /hooks/actions.ts,并进行监听
<script lang="ts">
import { defineComponent, onMounted } from "vue";
import actions from "@/hooks/actions"; // 引入
export default defineComponent({
setup() {
onMounted(() => {
/**
* 注册一个观察者函数
* @param state 变更后的状态
* @param prevState: 变更前的状态
*/
actions.onGlobalStateChange(
(state: { token: any }, prevState: { token: any }) => {
console.log("微应用观察者:token 改变前的值为 ", prevState.token);
console.log(
"微应用观察者:token 改变后的值为 ",
state.token
);
}
);
});
},
});
</script>
打印结果:
解释如下:
主应用登录前:token = undefined
主应用登录后:token = 时间111
微应用加载前:token = undefined
微应用加载后:token = 时间111(被主应用传递过来的)
微应用内改变了 token 后,主应用和微应用同时触发了观察者数 actions.onGlobalStateChange;
改变前,主应用微应用中的 token = 时间111;
改变后,主应用微应用中的 token = 时间222;
4. socket.io
暂无示例
5. 通信方式对比
5.1 使用 props 进行通信
优点:
- 使用简单
- 适合初次加载微应用时传递消息
缺点:
- 微应用独立运行时,无法使用
- 微应用需要先了解状态池的内容,再进行通信
- 微应用挂载后,不能实时监听
5.2 使用 qiankun 提供的 API initGlobalState 进行通信
优点:
- 使用简单,官方支持性高
- 适合通信较少的业务场景
- 可实现实时监听
缺点:
- 微应用独立运行时,无法使用
- 微应用需要先了解状态池的内容,再进行通信
5.3 使用外部插件 socket.io 进行通信
优点:
- 微应用不受主应用影响,可以独立运行
- 不限使用场景
- 可实现实时监听
缺点:
- 需要写服务端代码
- 不会使用的,需要学习成本
更多推荐
所有评论(0)