@wonderkits/app
Version:
WonderKits micro-frontend SDK for sub-applications
188 lines (185 loc) • 5.06 kB
JavaScript
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