美文网首页
微前端工程之间的通讯

微前端工程之间的通讯

作者: Yong_bcf4 | 来源:发表于2020-07-07 19:37 被阅读0次

微前端工程之间的通讯

原理

使用发布订阅者模式:一方订阅,一方发布。

使用单例模式:一个工程内使用同一个实例。

微前端加载,首先加载父工程,随后根据配置加载对应的一个或者多个子工程。

父工程先一步生成实例,并传递给子工程。子工程则使用这个实例初始化自己的实例。 共享同一个实例。

代码

import { getState } from "./utils";

let instance: BusInstance | null = null;

class BusInstance {

private queue: Function[] = [];

subscription = (cb: Function) => {

this.queue.push(cb);

};

unsubscription = (cb: Function) => {

this.queue = this.queue.filter((item) => item !== cb);

};

notify = (data: any) => {

this.queue.forEach((cb) => {

if ("[object Function]" === Object.prototype.toString.call(cb)) {

cb(data);

}

});

};

}

export function init(value: BusInstance) {

// 父工程将自己的 bus 实例,传递给子工程

// 子工程调用 init 函数,这样父子工程共享同一个实例

instance = value;

}

export default function Bus() {

// 使用单例模式

// 除了第一次返回的都是同一个实例

if (!instance) {

instance = new BusInstance();

}

return instance;

}

export function subscription(func: Function) {

const bus = Bus();

bus.subscription(func);

}

export function unsubscription(func: Function) {

const bus = Bus();

bus.unsubscription(func);

}

export function notify(data: { type: string; payload: any }) {

const bus = Bus();

// 使用 setTimeout 原因是,防止在 reducer 中调用 notify 函数,导致触发另外一个

reducers

setTimeout(() => {

bus.notify(data);

});

}

export function destory() {

instance = null;

}

export function initGlobal(global: any) {

setTimeout(() => {

const [state, store] = getState();

if (store) {

store.dispatch({ type: "global/initGlobal", payload: global() });

}

});

}

使用以 @umijs/plugin-qiankun 为例

本质上使用 single-spa 用法一致,主要是需要共享实例。

主工程

import Bus from "@static/common/bus";

import { getState, cloneDeep } from "@static/common/utils";

export const qiankun = function () {

return Promise.resolve({

apps: window.SUB_APP_CONFIG.map(({ name, entry, base }) => ({

name,

entry,

base,

props: {

// 父工程生成实例传递给子工程

3 / 5

bus: Bus(),

global() {

const [state] = getState();

if (state) {

return cloneDeep(state.global);

}

return {};

},

},

})),

prefetch: true,

defer: true,

lifeCycles: {

beforeLoad() {

loadingFn(true);

},

beforeMount() {

loadingFn(false);

},

},

});

};

import { Effect, qiankunStart, Reducer } from "umi";

import { getSideOptions, getState } from "@static/common/utils";

import { notify, subscription } from "@static/common/bus";

import globalModel, { GlobalState } from "@static/models/global";

const { namespace, state, reducers, effects, subscriptions } = globalModel;

const newEffects: {

[index: string]: Effect;

} = {

...effects,

*authUserInfo(anyAction, effectsCommandMap) {

if (effects) {

yield effects.authUserInfo(anyAction, effectsCommandMap);

if (window.singleSpaNavigate) {

setTimeout(() => {

qiankunStart();

});

}

}

},

};

const newReduccers: {

[index: string]: Reducer<GlobalState | undefined>;

} = {

...reducers,

updateCollapsed(state, { payload }) {

4 / 5

if (!state) return state;

state.collapsed = payload;

// 发布消息

notify({ type: "global/updateCollapsed", payload });

if (payload) {

state.nav.openKeys = "";

} else {

const { openKeys } = getSideOptions(state.nav.data || []);

state.nav.openKeys = openKeys;

}

state.nav = { ...state.nav };

return { ...state };

},

};

export default {

namespace,

state,

reducers: newReduccers,

effects: newEffects,

subscriptions,

};

子工程

import {

initGlobal,

init,

destory,

subscription,

unsubscription,

} from "@static/common/bus";

import { getState } from "@static/common/utils";

function baseFunc(data: any) {

const [, store] = getState();

if (store) {

const { type, payload } = data;

if ("global/updateCollapsed" === type) {

store.dispatch({ type, payload });

}

}

}

export const qiankun = function () {

if (window.singleSpaNavigate) {

return {

async bootstrap(props: any) {

// 共享实例

init(props.bus);

// 订阅

5 / 5

subscription(baseFunc);

},

async mount(props: any) {

initGlobal(props.global);

},

async unmount() {

// 取消订阅

unsubscription(baseFunc);

destory();

},

};

}

return Promise.resolve();

};

注意:理论上只要共享了实例,可以是父子、兄弟等等之间互相发送消息

相关文章

网友评论

      本文标题:微前端工程之间的通讯

      本文链接:https://www.haomeiwen.com/subject/pcrhcktx.html