export function mount()

in packages/react/react-portal/src/mount.tsx [57:170]


export function mount<T extends EmitterProps>(App: AppComponent<T>, container?: Element | null, id?: string) {
  class ConsoleApp extends React.Component<EmitterProps & IProps> {
    constructor(props) {
      super(props);

      // @deprecated
      if (props.__enableInitialHistoryAction && props?.appProps?.path && props?.appProps?.path !== getPathNameWithQueryAndSearch()) {
        window.history.replaceState(null, null, props?.appProps?.path);
      }
    }

    componentDidCatch() { /* Empty */ }

    componentDidMount() { /* Empty */ }

    componentWillUnmount() { /* Empty */ }

    render() {
      const props = getProps(this.props);
      const { logger, appDidCatch } = props;
      const contextValue: IContextProps = {
        inOsSandBox: isOsContext(),
        appProps: props,
      };

      return (
        <ErrorBoundary
          logger={logger}
          appDidCatch={appDidCatch}
        >
          { Context ? (
            <Context.Provider value={contextValue}>
              <App {...Object.assign(props || {})} />
            </Context.Provider>
          ) : <App {...Object.assign(props || {})} />
          }
        </ErrorBoundary>
      );
    }
  }

  // 如果外部被其他沙箱嵌套,沙箱销毁时一旦清除全局变量,isOsBundle 拿到的值将为 false
  // 需要综合判断
  if (isOsBundle() || isOsContext() || isAlfaScript()) {
    const reactLifeCycles = SingleSpaReact({
      React,
      ReactDOM,
      rootComponent: ConsoleApp,
      domElementGetter: () => document.getElementsByTagName(id)[0],
    });

    /**
     * 针对 外跳 的路由提供简单的方式通知宿主
     * @param e 点击事件
     */
    let handleExternalLinks;

    return {
      bootstrap: [
        reactLifeCycles.bootstrap,
      ],
      mount: [
        reactLifeCycles.mount,
        // 全局事件托管
        async (props) => {
          const { domElement } = props;
          const { emitter, name } = getProps(props);

          bindEvents(emitter);

          if (isOsContext()) {
            handleExternalLinks = (e: Event) => {
              const target = e.target as HTMLAnchorElement;
              if (target.tagName === 'A' && target.hasAttribute('data-alfa-external-router')) {
                e.preventDefault();
                e.stopPropagation();
                emitter && emitter.emit(`${name || id}:external-router`, target.getAttribute('href'));
              }
            };
            domElement?.addEventListener('click', handleExternalLinks, true);
          }
        },
      ],
      unmount: [
        // 注销全局事件托管
        async (props) => {
          const { domElement } = props;
          const { emitter } = getProps(props);

          unbindEvents(emitter);

          if (isOsContext() && handleExternalLinks) {
            domElement?.removeEventListener('click', handleExternalLinks, true);
            handleExternalLinks = undefined;
          }
        },
        reactLifeCycles.unmount,
      ],
      update: [
        reactLifeCycles.update,
      ],
      exposedModule: exposeModuleMap,
    };
  } else {
    // @ts-ignore;
    if (ReactDOM.createRoot) {
      // @ts-ignore;
      ReactDOM.createRoot(container).render(<ConsoleApp />);
      return;
    }

    ReactDOM.render(<ConsoleApp />, container);
  }
}