@@ -3,6 +3,7 @@ var addClass = _.addClass
3
3
var removeClass = _ . removeClass
4
4
var transDurationProp = _ . transitionProp + 'Duration'
5
5
var animDurationProp = _ . animationProp + 'Duration'
6
+ var doc = typeof document === 'undefined' ? null : document
6
7
7
8
var TYPE_TRANSITION = 1
8
9
var TYPE_ANIMATION = 2
@@ -19,15 +20,17 @@ var queued = false
19
20
* @param {Function } op - the actual dom operation
20
21
* @param {String } cls - the className to remove when the
21
22
* transition is done.
23
+ * @param {Vue } vm
22
24
* @param {Function } [cb] - user supplied callback.
23
25
*/
24
26
25
- function push ( el , dir , op , cls , cb ) {
27
+ function push ( el , dir , op , cls , vm , cb ) {
26
28
queue . push ( {
27
29
el : el ,
28
30
dir : dir ,
29
31
cb : cb ,
30
32
cls : cls ,
33
+ vm : vm ,
31
34
op : op
32
35
} )
33
36
if ( ! queued ) {
@@ -61,44 +64,69 @@ function run (job) {
61
64
62
65
var el = job . el
63
66
var data = el . __v_trans
67
+ var hooks = data . hooks
64
68
var cls = job . cls
65
69
var cb = job . cb
66
70
var op = job . op
71
+ var vm = job . vm
67
72
var transitionType = getTransitionType ( el , data , cls )
68
73
69
74
if ( job . dir > 0 ) { // ENTER
75
+
76
+ // call javascript enter hook
77
+ if ( hooks && hooks . enter ) {
78
+ var expectsCb = hooks . enter . length > 1
79
+ if ( expectsCb ) {
80
+ data . hookCb = function ( ) {
81
+ data . hookCancel = data . hookCb = null
82
+ if ( hooks . afterEnter ) {
83
+ hooks . afterEnter . call ( vm , el )
84
+ }
85
+ if ( cb ) cb ( )
86
+ }
87
+ }
88
+ data . hookCancel = hooks . enter . call ( vm , el , data . hookCb )
89
+ }
90
+
70
91
if ( transitionType === TYPE_TRANSITION ) {
71
92
// trigger transition by removing enter class
72
93
removeClass ( el , cls )
73
- // only need to listen for transitionend if there's
74
- // a user callback
75
- if ( cb ) setupTransitionCb ( _ . transitionEndEvent )
94
+ setupTransitionCb ( _ . transitionEndEvent )
76
95
} else if ( transitionType === TYPE_ANIMATION ) {
77
96
// animations are triggered when class is added
78
97
// so we just listen for animationend to remove it.
79
98
setupTransitionCb ( _ . animationEndEvent , function ( ) {
80
99
removeClass ( el , cls )
81
100
} )
82
- } else {
101
+ } else if ( ! data . hookCb ) {
83
102
// no transition applicable
84
103
removeClass ( el , cls )
85
- if ( cb ) cb ( )
104
+ if ( hooks && hooks . afterEnter ) {
105
+ hooks . afterEnter . call ( vm , el )
106
+ }
107
+ if ( cb ) {
108
+ cb ( )
109
+ }
86
110
}
111
+
87
112
} else { // LEAVE
88
- if ( transitionType ) {
89
- // leave transitions/animations are both triggered
90
- // by adding the class, just remove it on end event.
91
- var event = transitionType === TYPE_TRANSITION
92
- ? _ . transitionEndEvent
93
- : _ . animationEndEvent
94
- setupTransitionCb ( event , function ( ) {
113
+ // only need to handle leave if there's no hook callback
114
+ if ( ! data . hookCb ) {
115
+ if ( transitionType ) {
116
+ // leave transitions/animations are both triggered
117
+ // by adding the class, just remove it on end event.
118
+ var event = transitionType === TYPE_TRANSITION
119
+ ? _ . transitionEndEvent
120
+ : _ . animationEndEvent
121
+ setupTransitionCb ( event , function ( ) {
122
+ op ( )
123
+ removeClass ( el , cls )
124
+ } )
125
+ } else {
95
126
op ( )
96
127
removeClass ( el , cls )
97
- } )
98
- } else {
99
- op ( )
100
- removeClass ( el , cls )
101
- if ( cb ) cb ( )
128
+ if ( cb ) cb ( )
129
+ }
102
130
}
103
131
}
104
132
@@ -119,7 +147,17 @@ function run (job) {
119
147
_ . off ( el , event , onEnd )
120
148
data . event = data . callback = null
121
149
if ( cleanupFn ) cleanupFn ( )
122
- if ( cb ) cb ( )
150
+ if ( ! data . hookCb ) {
151
+ if ( job . dir > 0 && hooks && hooks . afterEnter ) {
152
+ hooks . afterEnter . call ( vm , el )
153
+ }
154
+ if ( job . dir < 0 && hooks && hooks . afterLeave ) {
155
+ hooks . afterLeave . call ( vm , el )
156
+ }
157
+ if ( cb ) {
158
+ cb ( )
159
+ }
160
+ }
123
161
}
124
162
}
125
163
_ . on ( el , event , onEnd )
@@ -137,6 +175,14 @@ function run (job) {
137
175
*/
138
176
139
177
function getTransitionType ( el , data , className ) {
178
+ // skip CSS transitions if page is not visible -
179
+ // this solves the issue of transitionend events not
180
+ // firing until the page is visible again.
181
+ // pageVisibility API is supported in IE10+, same as
182
+ // CSS transitions.
183
+ if ( ! _ . transitionEndEvent || ( doc && doc . hidden ) ) {
184
+ return
185
+ }
140
186
var type = data . cache && data . cache [ className ]
141
187
if ( type ) return type
142
188
var inlineStyles = el . style
@@ -168,9 +214,13 @@ function getTransitionType (el, data, className) {
168
214
* @param {Number } direction - 1: enter, -1: leave
169
215
* @param {Function } op - the actual DOM operation
170
216
* @param {Object } data - target element's transition data
217
+ * @param {Vue } vm
218
+ * @param {Function } cb
171
219
*/
172
220
173
- module . exports = function ( el , direction , op , data , cb ) {
221
+ module . exports = function ( el , direction , op , data , vm , cb ) {
222
+ vm = el . __vue__ || vm
223
+ var hooks = data . hooks
174
224
var prefix = data . id || 'v'
175
225
var enterClass = prefix + '-enter'
176
226
var leaveClass = prefix + '-leave'
@@ -181,12 +231,42 @@ module.exports = function (el, direction, op, data, cb) {
181
231
removeClass ( el , leaveClass )
182
232
data . event = data . callback = null
183
233
}
234
+ // cancel function from js hooks
235
+ if ( data . hookCancel ) {
236
+ data . hookCancel ( )
237
+ data . hookCancel = null
238
+ }
184
239
if ( direction > 0 ) { // enter
240
+ // enter class
185
241
addClass ( el , enterClass )
242
+ // js hook
243
+ if ( hooks && hooks . beforeEnter ) {
244
+ hooks . beforeEnter . call ( vm , el )
245
+ }
186
246
op ( )
187
- push ( el , direction , null , enterClass , cb )
247
+ push ( el , direction , null , enterClass , vm , cb )
188
248
} else { // leave
249
+ if ( hooks && hooks . beforeLeave ) {
250
+ hooks . beforeLeave . call ( vm , el )
251
+ }
252
+ // add leave class
189
253
addClass ( el , leaveClass )
190
- push ( el , direction , op , leaveClass , cb )
254
+ // execute js leave hook
255
+ if ( hooks && hooks . leave ) {
256
+ var expectsCb = hooks . leave . length > 1
257
+ if ( expectsCb ) {
258
+ data . hookCb = function ( ) {
259
+ data . hookCancel = data . hookCb = null
260
+ op ( )
261
+ removeClass ( el , leaveClass )
262
+ if ( hooks && hooks . afterLeave ) {
263
+ hooks . afterLeave . call ( vm , el )
264
+ }
265
+ if ( cb ) cb ( )
266
+ }
267
+ }
268
+ data . hookCancel = hooks . leave . call ( vm , el , data . hookCb )
269
+ }
270
+ push ( el , direction , op , leaveClass , vm , cb )
191
271
}
192
272
}
0 commit comments