Преглед изворни кода

dom method callbacks should be async.

Evan You пре 12 година
родитељ
комит
070d5c0e58
3 измењених фајлова са 55 додато и 22 уклоњено
  1. 12 0
      src/utils.js
  2. 8 6
      src/viewmodel.js
  3. 35 16
      test/unit/specs/viewmodel.js

+ 12 - 0
src/utils.js

@@ -5,6 +5,11 @@ var config    = require('./config'),
     console   = window.console,
     ViewModel // late def
 
+var defer =
+    window.webkitRequestAnimationFrame ||
+    window.requestAnimationFrame ||
+    window.setTimeout
+
 /**
  *  Create a prototype-less object
  *  which is a better hash/map
@@ -180,5 +185,12 @@ var utils = module.exports = {
         if (!config.silent && console) {
             console.warn(join.call(arguments, ' '))
         }
+    },
+
+    /**
+     * Defer DOM updates
+     */
+    nextTick: function (cb) {
+        defer(cb, 0)
     }
 }

+ 8 - 6
src/viewmodel.js

@@ -1,6 +1,8 @@
 var Compiler   = require('./compiler'),
-    def        = require('./utils').defProtected,
-    transition = require('./transition')
+    utils      = require('./utils'),
+    transition = require('./transition'),
+    def        = utils.defProtected,
+    nextTick   = utils.nextTick
 
 /**
  *  ViewModel exposed to the user that holds data,
@@ -102,7 +104,7 @@ def(VMProto, '$appendTo', function (target, cb) {
     var el = this.$el
     transition(el, 1, function () {
         target.appendChild(el)
-        if (cb) cb()
+        if (cb) nextTick(cb)
     }, this.$compiler)
 })
 
@@ -112,7 +114,7 @@ def(VMProto, '$remove', function (cb) {
     if (!parent) return
     transition(el, -1, function () {
         parent.removeChild(el)
-        if (cb) cb()
+        if (cb) nextTick(cb)
     }, this.$compiler)
 })
 
@@ -123,7 +125,7 @@ def(VMProto, '$before', function (target, cb) {
     if (!parent) return
     transition(el, 1, function () {
         parent.insertBefore(el, target)
-        if (cb) cb()
+        if (cb) nextTick(cb)
     }, this.$compiler)
 })
 
@@ -139,7 +141,7 @@ def(VMProto, '$after', function (target, cb) {
         } else {
             parent.appendChild(el)
         }
-        if (cb) cb()
+        if (cb) nextTick(cb)
     }, this.$compiler)
 })
 

+ 35 - 16
test/unit/specs/viewmodel.js

@@ -217,7 +217,8 @@ describe('UNIT: ViewModel', function () {
 
         var enterCalled,
             leaveCalled,
-            callbackCalled
+            callbackCalled,
+            nextTick = require('vue/src/utils').nextTick
         
         var v = new Vue({
             attributes: {
@@ -247,16 +248,19 @@ describe('UNIT: ViewModel', function () {
             callbackCalled = true
         }
 
-        it('$appendTo', function () {
+        it('$appendTo', function (done) {
             reset()
             var parent = document.createElement('div')
             v.$appendTo(parent, cb)
             assert.strictEqual(v.$el.parentNode, parent)
             assert.ok(enterCalled)
-            assert.ok(callbackCalled)
+            nextTick(function () {
+                assert.ok(callbackCalled)
+                done()
+            })
         })
 
-        it('$before', function () {
+        it('$before', function (done) {
             reset()
             var parent = document.createElement('div'),
                 ref = document.createElement('div')
@@ -265,10 +269,13 @@ describe('UNIT: ViewModel', function () {
             assert.strictEqual(v.$el.parentNode, parent)
             assert.strictEqual(v.$el.nextSibling, ref)
             assert.ok(enterCalled)
-            assert.ok(callbackCalled)
+            nextTick(function () {
+                assert.ok(callbackCalled)
+                done()
+            })
         })
 
-        it('$after', function () {
+        it('$after', function (done) {
             reset()
             var parent = document.createElement('div'),
                 ref1 = document.createElement('div'),
@@ -280,17 +287,26 @@ describe('UNIT: ViewModel', function () {
             assert.strictEqual(v.$el.nextSibling, ref2)
             assert.strictEqual(ref1.nextSibling, v.$el)
             assert.ok(enterCalled)
-            assert.ok(callbackCalled)
-            reset()
-            v.$after(ref2, cb)
-            assert.strictEqual(v.$el.parentNode, parent)
-            assert.notOk(v.$el.nextSibling)
-            assert.strictEqual(ref2.nextSibling, v.$el)
-            assert.ok(enterCalled)
-            assert.ok(callbackCalled)
+            nextTick(function () {
+                assert.ok(callbackCalled)
+                next()
+            })
+
+            function next () {
+                reset()
+                v.$after(ref2, cb)
+                assert.strictEqual(v.$el.parentNode, parent)
+                assert.notOk(v.$el.nextSibling)
+                assert.strictEqual(ref2.nextSibling, v.$el)
+                assert.ok(enterCalled)
+                nextTick(function () {
+                    assert.ok(callbackCalled)
+                    done()
+                })
+            }
         })
 
-        it('$remove', function () {
+        it('$remove', function (done) {
             reset()
             var parent = document.createElement('div')
             v.$appendTo(parent)
@@ -298,7 +314,10 @@ describe('UNIT: ViewModel', function () {
             assert.notOk(v.$el.parentNode)
             assert.ok(enterCalled)
             assert.ok(leaveCalled)
-            assert.ok(callbackCalled)
+            nextTick(function () {
+                assert.ok(callbackCalled)
+                done()
+            })
         })
 
     })