fix: use addEventListener to bind iframe event handlers (#169)

* feat: use addEventListener to bind iframe event handlers

* fix: types
This commit is contained in:
864907600cc
2024-05-31 17:44:55 +08:00
committed by GitHub
parent 28040fc006
commit c1306e24e0
+39 -17
View File
@@ -3,7 +3,13 @@ import { TangoEventName } from '@music163/tango-helpers';
import Loading from './loading';
import Manager from './manager';
import { createMissingPackageJSON, changeRoute } from './helper';
import { IFiles, CodeSandboxState, CodeSandboxProps, UnsubscribeFunction } from '../types';
import {
IFiles,
CodeSandboxState,
CodeSandboxProps,
UnsubscribeFunction,
EventHandlers,
} from '../types';
// CodeSandbox 使用示例
// <CodeSandbox files={files} entry={entry} template={template} bundlerURL={`${window.location.protocol}//codesandbox.fn.netease.com/`} />
@@ -32,6 +38,8 @@ export class CodeSandbox extends React.Component<CodeSandboxProps, CodeSandboxSt
iframe: HTMLIFrameElement;
private eventHandlers: EventHandlers;
constructor(props: CodeSandboxProps) {
super(props);
@@ -75,11 +83,8 @@ export class CodeSandbox extends React.Component<CodeSandboxProps, CodeSandboxSt
this.manager.cleanup();
// clear tango event
if (this.iframe && this.props?.eventHandlers?.onTango) {
this.iframe.contentDocument?.removeEventListener(
TangoEventName.DesignerAction,
this.props.eventHandlers.onTango,
);
if (this.iframe && this.eventHandlers) {
this.unbindEvents(this.eventHandlers);
}
}
@@ -116,6 +121,29 @@ export class CodeSandbox extends React.Component<CodeSandboxProps, CodeSandboxSt
externalResources: this.props.externalResources,
});
normalizeEventType = (eventType: string) =>
eventType === 'onTango'
? TangoEventName.DesignerAction
: eventType.replace(/^on/, '').toLowerCase();
bindEvents = (eventHandlers: EventHandlers) => {
Object.keys(eventHandlers).forEach((eventType) => {
this.iframe?.contentDocument?.addEventListener(
this.normalizeEventType(eventType),
eventHandlers[eventType],
);
});
};
unbindEvents = (eventHandlers: EventHandlers) => {
Object.keys(eventHandlers).forEach((eventType) => {
this.iframe?.contentDocument?.removeEventListener(
this.normalizeEventType(eventType),
eventHandlers[eventType],
);
});
};
// Manager 实例化,即开始构建页面
// 将 el 传给 Manager 作为实例化参数,当构建完成后,会将构建的页面 dom 设置给 el
// 注:Manager是一个管理者的角色,从大局上把控整个转译和执行的流程
@@ -155,17 +183,11 @@ export class CodeSandbox extends React.Component<CodeSandboxProps, CodeSandboxSt
// 注册监听函数
const { eventHandlers } = this.props;
Object.keys(eventHandlers).forEach((eventType) => {
if (el.contentDocument) {
el.contentDocument[eventType.toLowerCase()] = eventHandlers[eventType];
}
if (eventType === 'onTango') {
el.contentDocument?.addEventListener(
TangoEventName.DesignerAction,
eventHandlers[eventType],
);
}
});
if (eventHandlers) {
this.bindEvents(eventHandlers);
// 保存一份当前的 eventHandlers,避免 props 变更导致无法取消现在已注册的事件绑定
this.eventHandlers = eventHandlers;
}
};
}
};