7
7
compatUtils ,
8
8
DeprecationTypes
9
9
} from '@vue/runtime-core'
10
- import { isObject , toNumber , extend } from '@vue/shared'
10
+ import { isObject , toNumber , extend , isArray } from '@vue/shared'
11
11
12
12
const TRANSITION = 'transition'
13
13
const ANIMATION = 'animation'
@@ -75,6 +75,35 @@ export const TransitionPropsValidators = (Transition.props = /*#__PURE__*/ exten
75
75
DOMTransitionPropsValidators
76
76
) )
77
77
78
+ /**
79
+ * #3227 Incoming hooks may be merged into arrays when wrapping Transition
80
+ * with custom HOCs.
81
+ */
82
+ const callHook = (
83
+ hook : Function | Function [ ] | undefined ,
84
+ args : any [ ] = [ ]
85
+ ) => {
86
+ if ( isArray ( hook ) ) {
87
+ hook . forEach ( h => h ( ...args ) )
88
+ } else if ( hook ) {
89
+ hook ( ...args )
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Check if a hook expects a callback (2nd arg), which means the user
95
+ * intends to explicitly control the end of the transition.
96
+ */
97
+ const hasExplicitCallback = (
98
+ hook : Function | Function [ ] | undefined
99
+ ) : boolean => {
100
+ return hook
101
+ ? isArray ( hook )
102
+ ? hook . some ( h => h . length > 1 )
103
+ : hook . length > 1
104
+ : false
105
+ }
106
+
78
107
export function resolveTransitionProps (
79
108
rawProps : TransitionProps
80
109
) : BaseTransitionProps < Element > {
@@ -154,7 +183,7 @@ export function resolveTransitionProps(
154
183
return ( el : Element , done : ( ) => void ) => {
155
184
const hook = isAppear ? onAppear : onEnter
156
185
const resolve = ( ) => finishEnter ( el , isAppear , done )
157
- hook && hook ( el , resolve )
186
+ callHook ( hook , [ el , resolve ] )
158
187
nextFrame ( ( ) => {
159
188
removeTransitionClass ( el , isAppear ? appearFromClass : enterFromClass )
160
189
if ( __COMPAT__ && legacyClassEnabled ) {
@@ -164,7 +193,7 @@ export function resolveTransitionProps(
164
193
)
165
194
}
166
195
addTransitionClass ( el , isAppear ? appearToClass : enterToClass )
167
- if ( ! ( hook && hook . length > 1 ) ) {
196
+ if ( ! hasExplicitCallback ( hook ) ) {
168
197
whenTransitionEnds ( el , type , enterDuration , resolve )
169
198
}
170
199
} )
@@ -173,15 +202,15 @@ export function resolveTransitionProps(
173
202
174
203
return extend ( baseProps , {
175
204
onBeforeEnter ( el ) {
176
- onBeforeEnter && onBeforeEnter ( el )
205
+ callHook ( onBeforeEnter , [ el ] )
177
206
addTransitionClass ( el , enterFromClass )
178
207
if ( __COMPAT__ && legacyClassEnabled ) {
179
208
addTransitionClass ( el , legacyEnterFromClass )
180
209
}
181
210
addTransitionClass ( el , enterActiveClass )
182
211
} ,
183
212
onBeforeAppear ( el ) {
184
- onBeforeAppear && onBeforeAppear ( el )
213
+ callHook ( onBeforeAppear , [ el ] )
185
214
addTransitionClass ( el , appearFromClass )
186
215
if ( __COMPAT__ && legacyClassEnabled ) {
187
216
addTransitionClass ( el , legacyAppearFromClass )
@@ -205,23 +234,23 @@ export function resolveTransitionProps(
205
234
removeTransitionClass ( el , legacyLeaveFromClass )
206
235
}
207
236
addTransitionClass ( el , leaveToClass )
208
- if ( ! ( onLeave && onLeave . length > 1 ) ) {
237
+ if ( ! hasExplicitCallback ( onLeave ) ) {
209
238
whenTransitionEnds ( el , type , leaveDuration , resolve )
210
239
}
211
240
} )
212
- onLeave && onLeave ( el , resolve )
241
+ callHook ( onLeave , [ el , resolve ] )
213
242
} ,
214
243
onEnterCancelled ( el ) {
215
244
finishEnter ( el , false )
216
- onEnterCancelled && onEnterCancelled ( el )
245
+ callHook ( onEnterCancelled , [ el ] )
217
246
} ,
218
247
onAppearCancelled ( el ) {
219
248
finishEnter ( el , true )
220
- onAppearCancelled && onAppearCancelled ( el )
249
+ callHook ( onAppearCancelled , [ el ] )
221
250
} ,
222
251
onLeaveCancelled ( el ) {
223
252
finishLeave ( el )
224
- onLeaveCancelled && onLeaveCancelled ( el )
253
+ callHook ( onLeaveCancelled , [ el ] )
225
254
}
226
255
} as BaseTransitionProps < Element > )
227
256
}
0 commit comments