Skip to content

qiankun 主微应用传值详解 ​

在微前端架构中,主应用与微应用之间的通信是至关重要的。qiankun 提供了多种方式来实现数据传递,本文将详细介绍这两种主要的传值方式:props 和 global state,并提供最佳实践和代码示例。

1. Props 传值 ​

定义 ​

通过在微应用的配置中使用 props 属性,主应用可以将数据传递给微应用。

特点 ​

  • 单向传递:主应用可以将数据传递给微应用,但微应用无法直接修改主应用的数据。
  • 静态值:传递的值在微应用加载时确定,之后不会自动更新。

代码示例 ​

typescript
// src/utils/qiankun/microAppsConfig.ts
import eventBus from '../../common/MeshEditorJumper/eventBus.js';

interface QaSystemProps {
    eventBus: any;
    initQuery?: string;
    modelType?: string;
}

interface MicroAppConfig {
    name: string;
    entry: string;
    container: string;
    activeRule: string;
    sandbox: boolean | {
        experimentalStyleIsolation?: boolean;
        strictStyleIsolation?: boolean;
    };
    props?: QaSystemProps;
}

const microAppsConfig: MicroAppConfig[] = [
    {
        name: 'qaSystem',
        entry: window._env_.REACT_APP_SERVICE_QA_ENTRY,
        container: '#qaSystem-root',
        activeRule: '/qaSystem',
        sandbox: {
            experimentalStyleIsolation: true,
            strictStyleIsolation: false,
        },
        props: {
            eventBus: eventBus,
            initQuery: new Date().getTime() + '',
            modelType: '',
        }
    },
];

export { microAppsConfig };

优缺点 ​

  • 优点:
    • 简单易用,适合传递一些初始化数据。
    • 适合不需要频繁更新的数据。
  • 缺点:
    • 数据是静态的,无法响应主应用的状态变化。

2. Global State 传值 ​

定义 ​

通过 qiankun 提供的 initGlobalState 方法,可以创建一个全局状态管理,主应用和微应用都可以访问和修改这个状态。

特点 ​

  • 双向传递:主应用和微应用都可以读取和修改全局状态。
  • 动态变化:全局状态可以在运行时动态更新,微应用可以响应这些变化。

代码示例 ​

typescript
// src/utils/qiankun/action.ts
import { initGlobalState } from 'qiankun';

const initialState = {
    logInfo: {},
    subscriptionsInfo: {},
};

const actions = initGlobalState(initialState);
export default actions;

在微应用中使用全局状态:

typescript
// src/omnicraft/index.tsx
import { useEffect } from "react";
import action from "../utils/qiankun/action";

const MicroNode = ({
  handleCardClick,
  logInfo,
  subscriptionsInfo,
  handleOpenSub,
  handleOpenPre,
  handleOpenLogin,
  handleOpenFeedback,
}) => {
  useEffect(() => {
    action.setGlobalState({
      handleCardClick: (uuid: number) => handleCardClick(uuid),
      logInfo: logInfo,
      subscriptionsInfo: subscriptionsInfo,
      handleOpenSub: (value: boolean) => handleOpenSub(value),
      handleOpenPre: (value: boolean) => handleOpenPre(value),
      handleOpenLogin: (value: boolean) => handleOpenLogin(value),
      handleOpenFeedback: (value: boolean) => handleOpenFeedback(value),
    });
  }, [handleCardClick, logInfo, subscriptionsInfo, handleOpenLogin, handleOpenSub, handleOpenPre, handleOpenFeedback]);

  return (
    <div id="ominicraft-root"></div>
  );
};

export default MicroNode;

优缺点 ​

  • 优点:
    • 支持双向数据绑定,主应用和微应用可以实时同步状态。
    • 适合需要频繁更新和交互的数据。
  • 缺点:
    • 复杂性增加,可能导致状态管理混乱。

3. props + eventBus ​

1. 初始化config

ts
import eventBus from '../../common/MeshEditorJumper/eventBus.js';

interface QaSystemProps {
    eventBus: any;
    initQuery?: string;
    modelType?: string;
}

interface MicroAppConfig {
    name: string;
    entry: string;
    container: string;
    activeRule: string;
    sandbox: boolean | {
        experimentalStyleIsolation?: boolean;
        strictStyleIsolation?: boolean;
    };
    props?: QaSystemProps;
}

const microAppsConfig: MicroAppConfig[] = [
    {
        name: 'qaSystem',
        entry: window._env_.REACT_APP_SERVICE_QA_ENTRY,
        container: '#qaSystem-root',
        activeRule: '/qaSystem',
        sandbox: {
            experimentalStyleIsolation: true,
            strictStyleIsolation: false,
        },
        props: {
            eventBus: eventBus,
        }
    },
];

const MicroAppStart = function (){
    registerMicroApps(microAppsConfig);
    start({
        prefetch: "all",
        sandbox: false
    });
}

MicroAppStart();

2.构建一个eventBus

ts
class EventBus {
  constructor() {
    this.events = {};
    this.stickyEvents = {};
  }

  on(eventName, callback, executeSticky = true) {
    if (!this.events[eventName]) {
      this.events[eventName] = [];
    }
    this.events[eventName].push(callback);

    // 如果有粘性事件,并且 executeSticky 为 true,立即执行
    if (executeSticky && this.stickyEvents[eventName]) {
      callback(this.stickyEvents[eventName]);
    }
  }

  emit(eventName, data, sticky = true) {
    // 如果 sticky 为 true,保存最新的事件数据
    if (sticky) {
      this.stickyEvents[eventName] = data;
    }

    const event = this.events[eventName];
    if (event) {
      event.forEach(callback => callback(data));
    }
  }

  // 清除特定事件的所有监听器
  off(eventName) {
    delete this.events[eventName];
  }

  // 清除特定事件的粘性数据
  clearSticky(eventName) {
    delete this.stickyEvents[eventName];
  }

  // 获取特定事件的粘性数据
  getStickyEvent(eventName) {
    return this.stickyEvents[eventName];
  }
}

export default new EventBus();

3.主微应用更新eventBus实现传参和接收

ts
eventBus.emit('qaSystemInitData', {
  initQuery: inputRef.current.value,
  modelType: selectedTopic.id
});

eventBus.on('qaSystemQuery', (data: { query: string; type: string }) => {
  if (data.query && data.type) {
    localStorage.setItem('qaSystem:initQuery', data.query);
    localStorage.setItem('qaSystem:modelType', data.type);
  }
});

eventBus.off('qaSystemQuery');

总结 ​

在选择传值方式时,可以根据具体的需求来决定:

  • 如果只需要传递一些初始化的静态数据,可以使用 props 传值。
  • 如果需要实现动态交互和状态同步,建议使用 global state 传值或者 eventBus。

这两种方式可以结合使用,主应用可以通过 props 传递一些初始值,同时使用 global state 进行动态数据的管理。这样可以充分利用两者的优点,构建一个灵活且高效的微前端架构。