UNPKG

@wonderkits/app

Version:

WonderKits micro-frontend SDK for sub-applications

188 lines (185 loc) 5.06 kB
import { useState, useEffect, useMemo, useCallback } from 'react'; /** * @wonderkits/app/wujie * * Wujie 微前端集成工具 * 为子应用提供简单易用的 Wujie 环境检测和通信能力 */ /** * 获取 Wujie 环境信息(非 Hook 版本) * 用于在非 React 组件中获取 Wujie 状态 */ function getWujieContext() { const isInWujie = typeof window !== 'undefined' && !!window.__POWERED_BY_WUJIE__; const props = (isInWujie && window.$wujie?.props) || {}; const appId = props.appId; return { isInWujie, props, appId, }; } /** * 获取 Wujie 事件总线(非 Hook 版本) */ function getWujieBus() { const bus = window.$wujie?.bus; return { emit: (event, data) => { if (bus) { bus.$emit(event, data); } else { console.warn('[Wujie] Not in Wujie environment, cannot emit event:', event); } }, on: (event, callback) => { if (bus) { bus.$on(event, callback); return () => bus.$off(event, callback); } console.warn('[Wujie] Not in Wujie environment, cannot listen to event:', event); return () => { }; }, off: (event, callback) => { if (bus) { bus.$off(event, callback); } }, }; } /** * Wujie 集成 Hook * * 提供 Wujie 环境检测、通信和路由同步功能 * * @example * ```tsx * function MyComponent() { * const { context, bus, notifyRouteChange } = useWujie(); * * // 检查是否在 Wujie 环境 * if (!context.isInWujie) { * return <div>独立运行模式</div>; * } * * // 发送消息给父应用 * const handleClick = () => { * bus.emit('child-message', { type: 'click', data: 'hello' }); * }; * * // 监听父应用消息 * useEffect(() => { * return bus.on('parent-message', (data) => { * console.log('收到父应用消息:', data); * }); * }, []); * * return <button onClick={handleClick}>发送消息</button>; * } * ``` */ function useWujie() { // 初始化 context const [context, setContext] = useState(() => getWujieContext()); // 组件挂载时更新 context(处理 SSR 场景) useEffect(() => { setContext(getWujieContext()); }, []); // 创建稳定的 bus 引用 const bus = useMemo(() => getWujieBus(), []); // 通知路由变化 const notifyRouteChange = useCallback((path) => { if (context.isInWujie) { bus.emit('sub-route-change', { appId: context.appId, path, timestamp: Date.now(), }); } }, [context.isInWujie, context.appId, bus]); // 监听父应用路由变化 const onParentRouteChange = useCallback((callback) => { return bus.on('parent-route-change', (data) => { const routeData = data; if (routeData?.path) { callback(routeData.path); } }); }, [bus]); return { context, bus, notifyRouteChange, onParentRouteChange, }; } /** * 自动路由同步 Hook * * 自动监听 React Router 路由变化并通知父应用 * 需要配合 react-router-dom 使用 * * @example * ```tsx * import { useLocation } from 'react-router-dom'; * * function App() { * const location = useLocation(); * useWujieRouteSync(location.pathname); * return <Routes>...</Routes>; * } * ``` */ function useWujieRouteSync(currentPath) { const { context, notifyRouteChange } = useWujie(); useEffect(() => { if (context.isInWujie) { notifyRouteChange(currentPath); } }, [currentPath, context.isInWujie, notifyRouteChange]); } /** * 预定义的事件类型 * 子应用和主应用之间的标准通信协议 */ const WujieEvents = { /** 子应用路由变化 */ SUB_ROUTE_CHANGE: 'sub-route-change', /** 子应用就绪 */ SUB_APP_READY: 'sub-app-ready', /** 子应用错误 */ SUB_APP_ERROR: 'sub-app-error', /** 子应用消息 */ SUB_APP_MESSAGE: 'sub-app-message', /** 父应用路由变化 */ PARENT_ROUTE_CHANGE: 'parent-route-change', /** 父应用消息 */ PARENT_APP_MESSAGE: 'parent-app-message', }; /** * 子应用就绪通知 * 在子应用初始化完成后调用 */ function notifyAppReady(appId, version) { const bus = getWujieBus(); bus.emit(WujieEvents.SUB_APP_READY, { appId, version, timestamp: Date.now(), }); } /** * 子应用错误通知 * 在子应用发生错误时调用 */ function notifyAppError(appId, error) { const bus = getWujieBus(); bus.emit(WujieEvents.SUB_APP_ERROR, { appId, error, timestamp: Date.now(), }); } export { WujieEvents, getWujieBus, getWujieContext, notifyAppError, notifyAppReady, useWujie, useWujieRouteSync }; //# sourceMappingURL=wujie.esm.js.map