Browse Source

fix v-repeat diff algorithm for v-transition

Evan You 12 years ago
parent
commit
a575cbb01f
3 changed files with 29 additions and 18 deletions
  1. 1 1
      src/compiler.js
  2. 18 2
      src/directives/repeat.js
  3. 10 15
      src/viewmodel.js

+ 1 - 1
src/compiler.js

@@ -863,7 +863,7 @@ CompilerProto.destroy = function () {
     }
     }
     el.vue_vm = null
     el.vue_vm = null
 
 
-    this.destroyed = true
+    compiler.destroyed = true
     // emit destroy hook
     // emit destroy hook
     compiler.execHook('afterDestroy')
     compiler.execHook('afterDestroy')
 
 

+ 18 - 2
src/directives/repeat.js

@@ -94,6 +94,7 @@ module.exports = {
             oldIndex,
             oldIndex,
             targetNext,
             targetNext,
             currentNext,
             currentNext,
+            nextEl,
             ctn    = this.container,
             ctn    = this.container,
             oldVMs = this.oldVMs,
             oldVMs = this.oldVMs,
             vms    = []
             vms    = []
@@ -156,12 +157,27 @@ module.exports = {
             item = vm.$data
             item = vm.$data
             targetNext = vms[i + 1]
             targetNext = vms[i + 1]
             if (vm.$reused) {
             if (vm.$reused) {
-                currentNext = vm.$el.nextSibling.vue_vm
+                nextEl = vm.$el.nextSibling
+                // destroyed VMs' element might still be in the DOM
+                // due to transitions
+                while (!nextEl.vue_vm && nextEl !== this.ref) {
+                    nextEl = nextEl.nextSibling
+                }
+                currentNext = nextEl.vue_vm
                 if (currentNext !== targetNext) {
                 if (currentNext !== targetNext) {
                     if (!targetNext) {
                     if (!targetNext) {
                         ctn.insertBefore(vm.$el, this.ref)
                         ctn.insertBefore(vm.$el, this.ref)
                     } else {
                     } else {
-                        ctn.insertBefore(vm.$el, targetNext.$el)
+                        nextEl = targetNext.$el
+                        // new VMs' element might not be in the DOM yet
+                        // due to transitions
+                        while (!nextEl.parentNode) {
+                            targetNext = vms[nextEl.vue_vm.$index + 1]
+                            nextEl = targetNext
+                                ? targetNext.$el
+                                : this.ref
+                        }
+                        ctn.insertBefore(vm.$el, nextEl)
                     }
                     }
                 }
                 }
                 delete vm.$reused
                 delete vm.$reused

+ 10 - 15
src/viewmodel.js

@@ -131,37 +131,32 @@ def(VMProto, '$appendTo', function (target, cb) {
 })
 })
 
 
 def(VMProto, '$remove', function (cb) {
 def(VMProto, '$remove', function (cb) {
-    var el = this.$el,
-        parent = el.parentNode
-    if (!parent) return
+    var el = this.$el
     transition(el, -1, function () {
     transition(el, -1, function () {
-        parent.removeChild(el)
+        if (el.parentNode) {
+            el.parentNode.removeChild(el)
+        }
         if (cb) nextTick(cb)
         if (cb) nextTick(cb)
     }, this.$compiler)
     }, this.$compiler)
 })
 })
 
 
 def(VMProto, '$before', function (target, cb) {
 def(VMProto, '$before', function (target, cb) {
     target = query(target)
     target = query(target)
-    var el = this.$el,
-        parent = target.parentNode
-    if (!parent) return
+    var el = this.$el
     transition(el, 1, function () {
     transition(el, 1, function () {
-        parent.insertBefore(el, target)
+        target.parentNode.insertBefore(el, target)
         if (cb) nextTick(cb)
         if (cb) nextTick(cb)
     }, this.$compiler)
     }, this.$compiler)
 })
 })
 
 
 def(VMProto, '$after', function (target, cb) {
 def(VMProto, '$after', function (target, cb) {
     target = query(target)
     target = query(target)
-    var el = this.$el,
-        parent = target.parentNode,
-        next = target.nextSibling
-    if (!parent) return
+    var el = this.$el
     transition(el, 1, function () {
     transition(el, 1, function () {
-        if (next) {
-            parent.insertBefore(el, next)
+        if (target.nextSibling) {
+            target.parentNode.insertBefore(el, target.nextSibling)
         } else {
         } else {
-            parent.appendChild(el)
+            target.parentNode.appendChild(el)
         }
         }
         if (cb) nextTick(cb)
         if (cb) nextTick(cb)
     }, this.$compiler)
     }, this.$compiler)