Skip to content

Commit c1306e2

Browse files
authored
fix: use addEventListener to bind iframe event handlers (#169)
* feat: use addEventListener to bind iframe event handlers * fix: types
1 parent 28040fc commit c1306e2

File tree

1 file changed

+39
-17
lines changed

1 file changed

+39
-17
lines changed

packages/sandbox/src/code-sandbox/index.tsx

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@ import { TangoEventName } from '@music163/tango-helpers';
33
import Loading from './loading';
44
import Manager from './manager';
55
import { createMissingPackageJSON, changeRoute } from './helper';
6-
import { IFiles, CodeSandboxState, CodeSandboxProps, UnsubscribeFunction } from '../types';
6+
import {
7+
IFiles,
8+
CodeSandboxState,
9+
CodeSandboxProps,
10+
UnsubscribeFunction,
11+
EventHandlers,
12+
} from '../types';
713

814
// CodeSandbox 使用示例
915
// <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
3238

3339
iframe: HTMLIFrameElement;
3440

41+
private eventHandlers: EventHandlers;
42+
3543
constructor(props: CodeSandboxProps) {
3644
super(props);
3745

@@ -75,11 +83,8 @@ export class CodeSandbox extends React.Component<CodeSandboxProps, CodeSandboxSt
7583
this.manager.cleanup();
7684

7785
// clear tango event
78-
if (this.iframe && this.props?.eventHandlers?.onTango) {
79-
this.iframe.contentDocument?.removeEventListener(
80-
TangoEventName.DesignerAction,
81-
this.props.eventHandlers.onTango,
82-
);
86+
if (this.iframe && this.eventHandlers) {
87+
this.unbindEvents(this.eventHandlers);
8388
}
8489
}
8590

@@ -116,6 +121,29 @@ export class CodeSandbox extends React.Component<CodeSandboxProps, CodeSandboxSt
116121
externalResources: this.props.externalResources,
117122
});
118123

124+
normalizeEventType = (eventType: string) =>
125+
eventType === 'onTango'
126+
? TangoEventName.DesignerAction
127+
: eventType.replace(/^on/, '').toLowerCase();
128+
129+
bindEvents = (eventHandlers: EventHandlers) => {
130+
Object.keys(eventHandlers).forEach((eventType) => {
131+
this.iframe?.contentDocument?.addEventListener(
132+
this.normalizeEventType(eventType),
133+
eventHandlers[eventType],
134+
);
135+
});
136+
};
137+
138+
unbindEvents = (eventHandlers: EventHandlers) => {
139+
Object.keys(eventHandlers).forEach((eventType) => {
140+
this.iframe?.contentDocument?.removeEventListener(
141+
this.normalizeEventType(eventType),
142+
eventHandlers[eventType],
143+
);
144+
});
145+
};
146+
119147
// Manager 实例化,即开始构建页面
120148
// 将 el 传给 Manager 作为实例化参数,当构建完成后,会将构建的页面 dom 设置给 el
121149
// 注:Manager是一个管理者的角色,从大局上把控整个转译和执行的流程
@@ -155,17 +183,11 @@ export class CodeSandbox extends React.Component<CodeSandboxProps, CodeSandboxSt
155183

156184
// 注册监听函数
157185
const { eventHandlers } = this.props;
158-
Object.keys(eventHandlers).forEach((eventType) => {
159-
if (el.contentDocument) {
160-
el.contentDocument[eventType.toLowerCase()] = eventHandlers[eventType];
161-
}
162-
if (eventType === 'onTango') {
163-
el.contentDocument?.addEventListener(
164-
TangoEventName.DesignerAction,
165-
eventHandlers[eventType],
166-
);
167-
}
168-
});
186+
if (eventHandlers) {
187+
this.bindEvents(eventHandlers);
188+
// 保存一份当前的 eventHandlers,避免 props 变更导致无法取消现在已注册的事件绑定
189+
this.eventHandlers = eventHandlers;
190+
}
169191
};
170192
}
171193
};

0 commit comments

Comments
 (0)