فهرست منبع

100% coverage for v-repeat!

Evan You 11 سال پیش
والد
کامیت
a692b41499
2فایلهای تغییر یافته به همراه41 افزوده شده و 33 حذف شده
  1. 10 31
      src/directives/repeat.js
  2. 31 2
      test/unit/specs/directives/repeat_spec.js

+ 10 - 31
src/directives/repeat.js

@@ -219,17 +219,20 @@ module.exports = {
     // right place. We're going in reverse here because
     // insertBefore relies on the next sibling to be
     // resolved.
-    var targetNext, currentNext, nextEl
+    var targetNext, currentNext
     i = vms.length
     while (i--) {
       vm = vms[i]
       // this is the vm that we should be in front of
       targetNext = vms[i + 1]
       if (!targetNext) {
-        // This is the last item, just insert before the
-        // ref node. However we only want animation for
-        // newly created instances.
-        vm.$before(ref, null, !vm._reused)
+        // This is the last item. If it's reused then
+        // everything else will eventually be in the right
+        // place, so no need to touch it. Otherwise, insert
+        // it.
+        if (!vm._reused) {
+          vm.$before(ref)
+        }
       } else {
         if (vm._reused) {
           // this is the vm we are actually in front of
@@ -237,8 +240,7 @@ module.exports = {
           // we only need to move if we are not in the right
           // place already.
           if (currentNext !== targetNext) {
-            nextEl = findNextInDOMVmEl(targetNext, vms, ref)
-            vm.$before(nextEl, null, false)
+            vm.$before(targetNext.$el, null, false)
           }
         } else {
           // new instance, insert to existing next
@@ -435,36 +437,13 @@ module.exports = {
  */
 
 function findNextVm (vm, ref) {
-  var el = (vm._isBlock
-    ? vm._blockEnd
-    : vm.$el).nextSibling
+  var el = (vm._blockEnd || vm.$el).nextSibling
   while (!el.__vue__ && el !== ref) {
     el = el.nextSibling
   }
   return el.__vue__
 }
 
-/**
- * Helper to find the next vm that is already in the DOM
- * and return its $el. This is necessary because newly
- * inserted vms might not be in the DOM yet due to entering
- * transitions.
- *
- * @param {Vue} next
- * @param {Array} vms
- * @param {CommentNode} ref
- * @return {Element}
- */
-
-function findNextInDOMVmEl (next, vms, ref) {
-  var el = next.$el
-  while (!el.parentNode) {
-    next = vms[next.$index + 1]
-    el = next ? next.$el : ref
-  }
-  return el
-}
-
 /**
  * Attempt to convert non-Array objects to array.
  * This is the default filter installed to every v-repeat

+ 31 - 2
test/unit/specs/directives/repeat_spec.js

@@ -364,8 +364,37 @@ if (_.inBrowser) {
       expect(vm._children.length).toBe(0)
     })
 
-    it('with transition', function () {
-      // body...
+    it('with transition', function (done) {
+      // === IMPORTANT ===
+      // PhantomJS always returns false when calling
+      // Element.contains() on a comment node. This causes
+      // transitions to be skipped. Monkey patching here
+      // isn't ideal but does the job...
+      var inDoc = _.inDoc
+      _.inDoc = function () {
+        return true
+      }
+      var vm = new Vue({
+        el: el,
+        template: '<div v-repeat="items" v-transition="test">{{a}}</div>',
+        data: {
+          items: [{a:1}, {a:2}, {a:3}]
+        },
+        transitions: {
+          test: {
+            leave: function (el, done) {
+              setTimeout(done, 1)
+            }
+          }
+        }
+      })
+      vm.items.splice(1, 1, {a:4})
+      setTimeout(function () {
+        expect(el.innerHTML).toBe('<div>1</div><div>4</div><div>3</div><!--v-repeat-->')
+        // clean up
+        _.inDoc = inDoc
+        done()
+      }, 30)
     })
 
   })