feat: 支持全局广播事件

This commit is contained in:
yupeng12 2024-11-18 10:20:33 +08:00
parent 82efeba01d
commit 18f7087406
3 changed files with 77 additions and 9 deletions

View File

@ -26,7 +26,12 @@ import {
formateId
} from './utils/helper';
import {SimpleMap} from './utils/SimpleMap';
import {bindEvent, dispatchEvent, RendererEvent} from './utils/renderer-event';
import {
bindEvent,
bindGlobalEvent,
dispatchEvent,
RendererEvent
} from './utils/renderer-event';
import {isAlive} from 'mobx-state-tree';
import {reaction} from 'mobx';
import {resolveVariableAndFilter} from './utils/tpl-builtin';
@ -110,6 +115,7 @@ export class SchemaRenderer extends React.Component<SchemaRendererProps, any> {
toDispose: Array<() => any> = [];
unbindEvent: (() => void) | undefined = undefined;
unbindGlobalEvent: (() => void) | undefined = undefined;
isStatic: any = undefined;
constructor(props: SchemaRendererProps) {
@ -175,6 +181,7 @@ export class SchemaRenderer extends React.Component<SchemaRendererProps, any> {
this.toDispose.forEach(fn => fn());
this.toDispose = [];
this.unbindEvent?.();
this.unbindGlobalEvent?.();
this.removeAnimationStyle();
}
@ -299,7 +306,10 @@ export class SchemaRenderer extends React.Component<SchemaRendererProps, any> {
if (ref) {
// 这里无法区分监听的是不是广播所以又bind一下主要是为了绑广播
this.unbindEvent?.();
this.unbindGlobalEvent?.();
this.unbindEvent = bindEvent(ref);
this.unbindGlobalEvent = bindGlobalEvent(ref);
}
this.cRef = ref;
}

View File

@ -1,6 +1,6 @@
import {RendererProps} from '../factory';
import {createObject} from '../utils/helper';
import {RendererEvent, dispatchEvent} from '../utils/renderer-event';
import {RendererEvent, dispatchGlobalEvent} from '../utils/renderer-event';
import {
RendererAction,
ListenerAction,
@ -37,14 +37,17 @@ export class BroadcastAction implements RendererAction {
// 作为一个新的事件需要把广播动作的args参数追加到事件数据中
event.setData(createObject(event.data, action.data ?? {}));
const eventName = action.args?.eventName || action.eventName!;
return await dispatchGlobalEvent(eventName, action.data);
// 直接触发对应的动作
return await dispatchEvent(
action.args?.eventName || action.eventName!,
renderer,
event.context.scoped,
action.data,
event
);
// return await dispatchEvent(
// action.args?.eventName || action.eventName!,
// renderer,
// event.context.scoped,
// action.data,
// event
// );
}
}

View File

@ -195,6 +195,48 @@ export const bindEvent = (renderer: any) => {
return undefined;
};
export const bindGlobalEvent = (renderer: any) => {
if (!renderer) {
return undefined;
}
const listeners: EventListeners = renderer.props.$schema.onEvent;
let bcs: Array<{
renderer: any;
bc: BroadcastChannel;
}> = [];
if (listeners) {
for (let key of Object.keys(listeners)) {
const listener = listeners[key];
if (!BroadcastChannel) {
console.error('BroadcastChannel is not supported in your browser');
return;
}
const bc = new BroadcastChannel(key);
bcs.push({
renderer: renderer,
bc
});
bc.onmessage = e => {
const {eventName, data} = e.data;
const rendererEvent = createRendererEvent(eventName, {
env: renderer?.props?.env,
nativeEvent: eventName,
scoped: renderer?.context,
data
});
runActions(listener.actions, renderer, rendererEvent);
};
}
return () => {
bcs
.filter(item => item.renderer === renderer)
.forEach(item => item.bc.close());
};
}
return void 0;
};
// 触发事件
export async function dispatchEvent(
e: string | React.MouseEvent<any>,
@ -313,6 +355,19 @@ export async function dispatchEvent(
return Promise.resolve(rendererEvent);
}
export async function dispatchGlobalEvent(eventName: string, data: any) {
if (!BroadcastChannel) {
console.error('BroadcastChannel is not supported in your browser');
return;
}
const bc = new BroadcastChannel(eventName);
bc.postMessage({
eventName,
data
});
}
export const getRendererEventListeners = () => {
return rendererEventListeners;
};