diff --git a/packages/plugin-qiankun/src/master/MicroApp.tsx.tpl b/packages/plugin-qiankun/src/master/MicroApp.tsx.tpl index 5d27730e..310177b0 100644 --- a/packages/plugin-qiankun/src/master/MicroApp.tsx.tpl +++ b/packages/plugin-qiankun/src/master/MicroApp.tsx.tpl @@ -166,6 +166,10 @@ export const MicroApp = forwardRef( ...propsFromConfig, ...stateForSlave, ...propsFromParams, + globalRoutesInfo: { + masterHistoryType, + routes: globalSettings.routes + }, setLoading, }, }, @@ -223,6 +227,10 @@ export const MicroApp = forwardRef( ...propsFromConfig, ...stateForSlave, ...propsFromParams, + globalRoutesInfo: { + masterHistoryType, + routes: globalSettings.routes + }, setLoading, }; diff --git a/packages/plugin-qiankun/src/slave/MicroAppLink.tsx.tpl b/packages/plugin-qiankun/src/slave/MicroAppLink.tsx.tpl new file mode 100644 index 00000000..6439b12e --- /dev/null +++ b/packages/plugin-qiankun/src/slave/MicroAppLink.tsx.tpl @@ -0,0 +1,81 @@ +import { useModel } from '@@/plugin-model'; +import React, { forwardRef, FC, useImperativeHandle, useRef, MouseEvent, HTMLAttributes, useCallback } from 'react'; +import noop from "{{{ lodashPath }}}/noop"; +import find from "{{{ lodashPath }}}/find"; + +const COMPONENT_NAME = 'qiankun-microapp-link'; + +interface MicroAppLinkProps { + // 应用名称 + appName?: string; + + // 相对路由,不包含应用前缀 + appRoute: string; + + // 是否主应用下的路由,默认false + isMaster?: boolean; +} + +const urlFactory = (routes: Record[]) => ({ appName, appRoute, isMaster }: MicroAppLinkProps) => { + if (isMaster) { + return appRoute; + } + + const app = find(routes, ({ microApp }) => microApp === appName); + if (!app) { + console.error(`[${COMPONENT_NAME}] microapp "${app}" is not found`); + return appRoute; + } + + const prefix = app.path.replace('/*', ''); + return `${prefix}/${appRoute.startsWith('/') ? appRoute.slice(1) : appRoute}`; +}; + +export const MicroAppLink: FC> = forwardRef((props, ref) => { + const { + children, + appName, + appRoute, + isMaster = false, + ...anchorProps + } = props; + const stateFromMaster = (useModel || noop)('@@qiankunStateFromMaster'); + const linkRef = useRef(); + + const { historyType, routes } = stateFromMaster?.globalRoutesInfo || {}; + const linkProps = { appName, appRoute, isMaster }; + const createHerf = urlFactory(routes); + const linkUrl = historyType === 'hash' ? `#${createHerf(linkProps)}` : createHerf(linkProps); + + useImperativeHandle(ref, () => linkRef.current); + + const handleClick = useCallback((e: MouseEvent) => { + if (anchorProps.onClick) { + return anchorProps.onClick(e); + } + + // hash路由 使用 a标签 默认行为 + if (historyType === 'hash') { + return; + } + + if (historyType === 'browser') { + e?.stopPropagation(); + e?.preventDefault(); + return window.history.pushState({}, '', linkUrl); + } + + console.error(`[${COMPONENT_NAME}] not support "masterHistoryType = '${historyType}'"`) + return; + }, [anchorProps.onClick, historyType]); + + return ( + {children} + ); +}); diff --git a/packages/plugin-qiankun/src/slave/index.ts b/packages/plugin-qiankun/src/slave/index.ts index 4be7e2d3..7ca34900 100644 --- a/packages/plugin-qiankun/src/slave/index.ts +++ b/packages/plugin-qiankun/src/slave/index.ts @@ -214,6 +214,11 @@ export default function (api: IApi) { path: 'plugin-qiankun/lifecycles.ts', content: readFileSync(join(__dirname, 'lifecycles.ts.tpl'), 'utf-8'), }); + + api.writeTmpFile({ + path: 'plugin-qiankun/MicroAppLink.tsx', + content: readFileSync(join(__dirname, 'MicroAppLink.tsx.tpl'), 'utf-8'), + }); }); api.addMiddlewares(async () => {