@@ -3,6 +3,7 @@ var addClass = _.addClass
33var removeClass = _ . removeClass
44var transDurationProp = _ . transitionProp + 'Duration'
55var animDurationProp = _ . animationProp + 'Duration'
6+ var doc = typeof document === 'undefined' ? null : document
67
78var TYPE_TRANSITION = 1
89var TYPE_ANIMATION = 2
@@ -19,15 +20,17 @@ var queued = false
1920 * @param {Function } op - the actual dom operation
2021 * @param {String } cls - the className to remove when the
2122 * transition is done.
23+ * @param {Vue } vm
2224 * @param {Function } [cb] - user supplied callback.
2325 */
2426
25- function push ( el , dir , op , cls , cb ) {
27+ function push ( el , dir , op , cls , vm , cb ) {
2628 queue . push ( {
2729 el : el ,
2830 dir : dir ,
2931 cb : cb ,
3032 cls : cls ,
33+ vm : vm ,
3134 op : op
3235 } )
3336 if ( ! queued ) {
@@ -61,44 +64,69 @@ function run (job) {
6164
6265 var el = job . el
6366 var data = el . __v_trans
67+ var hooks = data . hooks
6468 var cls = job . cls
6569 var cb = job . cb
6670 var op = job . op
71+ var vm = job . vm
6772 var transitionType = getTransitionType ( el , data , cls )
6873
6974 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+
7091 if ( transitionType === TYPE_TRANSITION ) {
7192 // trigger transition by removing enter class
7293 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 )
7695 } else if ( transitionType === TYPE_ANIMATION ) {
7796 // animations are triggered when class is added
7897 // so we just listen for animationend to remove it.
7998 setupTransitionCb ( _ . animationEndEvent , function ( ) {
8099 removeClass ( el , cls )
81100 } )
82- } else {
101+ } else if ( ! data . hookCb ) {
83102 // no transition applicable
84103 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+ }
86110 }
111+
87112 } 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 {
95126 op ( )
96127 removeClass ( el , cls )
97- } )
98- } else {
99- op ( )
100- removeClass ( el , cls )
101- if ( cb ) cb ( )
128+ if ( cb ) cb ( )
129+ }
102130 }
103131 }
104132
@@ -119,7 +147,17 @@ function run (job) {
119147 _ . off ( el , event , onEnd )
120148 data . event = data . callback = null
121149 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+ }
123161 }
124162 }
125163 _ . on ( el , event , onEnd )
@@ -137,6 +175,14 @@ function run (job) {
137175 */
138176
139177function 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+ }
140186 var type = data . cache && data . cache [ className ]
141187 if ( type ) return type
142188 var inlineStyles = el . style
@@ -168,9 +214,13 @@ function getTransitionType (el, data, className) {
168214 * @param {Number } direction - 1: enter, -1: leave
169215 * @param {Function } op - the actual DOM operation
170216 * @param {Object } data - target element's transition data
217+ * @param {Vue } vm
218+ * @param {Function } cb
171219 */
172220
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
174224 var prefix = data . id || 'v'
175225 var enterClass = prefix + '-enter'
176226 var leaveClass = prefix + '-leave'
@@ -181,12 +231,42 @@ module.exports = function (el, direction, op, data, cb) {
181231 removeClass ( el , leaveClass )
182232 data . event = data . callback = null
183233 }
234+ // cancel function from js hooks
235+ if ( data . hookCancel ) {
236+ data . hookCancel ( )
237+ data . hookCancel = null
238+ }
184239 if ( direction > 0 ) { // enter
240+ // enter class
185241 addClass ( el , enterClass )
242+ // js hook
243+ if ( hooks && hooks . beforeEnter ) {
244+ hooks . beforeEnter . call ( vm , el )
245+ }
186246 op ( )
187- push ( el , direction , null , enterClass , cb )
247+ push ( el , direction , null , enterClass , vm , cb )
188248 } else { // leave
249+ if ( hooks && hooks . beforeLeave ) {
250+ hooks . beforeLeave . call ( vm , el )
251+ }
252+ // add leave class
189253 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 )
191271 }
192272}
0 commit comments