@@ -133,22 +133,41 @@ export function useShowController(
133
133
leaveBalloonSubject ,
134
134
) ;
135
135
case 'click' :
136
+ // 点击触发元素
136
137
const triggerClick$ = fromEvent ( el , 'click' ) . pipe (
138
+ // 因为 react 的合成事件是使用的事件委托机制,比直接监听 dom 的事件回调执行的要慢一步,所以加上延迟
137
139
delay ( 0 ) ,
140
+ // 排除被拦截的事件
138
141
filter ( ( e ) => ! e . defaultPrevented ) ,
139
142
) ;
140
- const outerEvent = fromOuterEvent (
143
+ // 按下 Esc 键
144
+ const keydownEscape$ = fromEvent < KeyboardEvent > (
145
+ window ,
146
+ 'keydown' ,
147
+ ) . pipe ( filter ( ( e ) => e . code === 'Escape' ) ) ;
148
+ // 点击除触发器与窗体之外的dom
149
+ const outerClick$ = fromOuterEvent (
141
150
( ) => [ el , balloonElRef . current ] ,
142
151
'click' ,
143
- ) . pipe ( tap ( close ) , takeUntil ( triggerClick$ ) , take ( 1 ) ) ;
144
- const queueEvent = triggerClick$ . pipe (
145
- switchMap ( ( ) => toggle ( ) . pipe ( takeWhile ( ( v ) => v ) ) ) ,
146
- switchMap ( ( ) => outerEvent ) ,
152
+ ) ;
153
+ // 关闭序列
154
+ const closeWaiter$ = merge ( outerClick$ , keydownEscape$ ) . pipe (
155
+ tap ( close ) ,
156
+ takeUntil ( triggerClick$ ) ,
157
+ take ( 1 ) ,
158
+ ) ;
159
+ // 开启序列
160
+ const openWaiter$ = triggerClick$ . pipe (
161
+ switchMap ( ( ) =>
162
+ // 监听 show 的变化,当 show 为 true 时结束监听并把控制权交给下一位
163
+ toggle ( ) . pipe ( takeWhile ( ( v ) => v ) ) ,
164
+ ) ,
165
+ switchMap ( ( ) => closeWaiter$ ) ,
147
166
) ;
148
167
// 当弹窗已经打开时(例如Button loading时会刷新该effect),添加点击和外部点击订阅
149
168
// 不然只有点击触发器才能外部点击订阅,否则如果很多popover的话会有一堆外部点击订阅
150
169
const clickSub = (
151
- show ? merge ( outerEvent , queueEvent ) : queueEvent
170
+ show ? merge ( closeWaiter$ , openWaiter$ ) : openWaiter$
152
171
) . subscribe ( ) ;
153
172
return clickSub . unsubscribe . bind ( clickSub ) ;
154
173
case 'focus' :
0 commit comments