Ver código fonte

wrap setTimeout in JavaScript effect functions

Evan You 12 anos atrás
pai
commit
63e9d72e61
2 arquivos alterados com 56 adições e 3 exclusões
  1. 27 3
      src/transition.js
  2. 29 0
      test/unit/specs/transition.js

+ 27 - 3
src/transition.js

@@ -3,6 +3,9 @@ var endEvents  = sniffEndEvents(),
     // batch enter animations so we only force the layout once
     Batcher    = require('./batcher'),
     batcher    = new Batcher(),
+    // cache timer functions
+    setTO      = window.setTimeout,
+    clearTO    = window.clearTimeout,
     // exit codes for testing
     codes = {
         CSS_E     : 1,
@@ -164,21 +167,42 @@ function applyTransitionFunctions (el, stage, changeState, effectId, compiler) {
     }
 
     var enter = funcs.enter,
-        leave = funcs.leave
+        leave = funcs.leave,
+        timeouts = el.vue_timeouts
+
+    // clear previous timeouts
+    if (timeouts) {
+        var i = timeouts.length
+        while (i--) {
+            clearTO(timeouts[i])
+        }
+    }
+
+    timeouts = el.vue_timeouts = []
+    function timeout (cb, delay) {
+        var id = setTO(function () {
+            cb()
+            timeouts.splice(timeouts.indexOf(id), 1)
+            if (!timeouts.length) {
+                el.vue_timeouts = null
+            }
+        }, delay)
+        timeouts.push(id)
+    }
 
     if (stage > 0) { // enter
         if (typeof enter !== 'function') {
             changeState()
             return codes.JS_SKIP_E
         }
-        enter(el, changeState)
+        enter(el, changeState, timeout)
         return codes.JS_E
     } else { // leave
         if (typeof leave !== 'function') {
             changeState()
             return codes.JS_SKIP_L
         }
-        leave(el, changeState)
+        leave(el, changeState, timeout)
         return codes.JS_L
     }
 

+ 29 - 0
test/unit/specs/transition.js

@@ -292,6 +292,35 @@ describe('UNIT: Transition', function () {
 
         })
 
+        describe('wrapped timeout', function () {
+            
+            var el = mockEl('js'),
+                c = mockChange(),
+                timerFired = false,
+                def = {
+                    enter: function (el, change, timeout) {
+                        change()
+                        timeout(function () {
+                            timerFired = true
+                        }, 0)
+                    },
+                    leave: function () {}
+                },
+                compiler = mockCompiler(def)
+
+            it('should cancel previous unfired timers', function (done) {
+                transition(el, 1, c.change, compiler)
+                assert.strictEqual(el.vue_timeouts.length, 1)
+                transition(el, -1, c.change, compiler)
+                assert.strictEqual(el.vue_timeouts.length, 0)
+                setTimeout(function () {
+                    assert.notOk(timerFired)
+                    done()
+                }, 0)
+            })
+
+        })
+
     })
 
     function mockChange (change) {