@@ -3,7 +3,13 @@ import { TangoEventName } from '@music163/tango-helpers';
3
3
import Loading from './loading' ;
4
4
import Manager from './manager' ;
5
5
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' ;
7
13
8
14
// CodeSandbox 使用示例
9
15
// <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
32
38
33
39
iframe : HTMLIFrameElement ;
34
40
41
+ private eventHandlers : EventHandlers ;
42
+
35
43
constructor ( props : CodeSandboxProps ) {
36
44
super ( props ) ;
37
45
@@ -75,11 +83,8 @@ export class CodeSandbox extends React.Component<CodeSandboxProps, CodeSandboxSt
75
83
this . manager . cleanup ( ) ;
76
84
77
85
// 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 ) ;
83
88
}
84
89
}
85
90
@@ -116,6 +121,29 @@ export class CodeSandbox extends React.Component<CodeSandboxProps, CodeSandboxSt
116
121
externalResources : this . props . externalResources ,
117
122
} ) ;
118
123
124
+ normalizeEventType = ( eventType : string ) =>
125
+ eventType === 'onTango'
126
+ ? TangoEventName . DesignerAction
127
+ : eventType . replace ( / ^ o n / , '' ) . 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
+
119
147
// Manager 实例化,即开始构建页面
120
148
// 将 el 传给 Manager 作为实例化参数,当构建完成后,会将构建的页面 dom 设置给 el
121
149
// 注:Manager是一个管理者的角色,从大局上把控整个转译和执行的流程
@@ -155,17 +183,11 @@ export class CodeSandbox extends React.Component<CodeSandboxProps, CodeSandboxSt
155
183
156
184
// 注册监听函数
157
185
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
+ }
169
191
} ;
170
192
}
171
193
} ;
0 commit comments