Просмотр исходного кода

properly clean up child when switching before wait-for fires (fix #1152)

Evan You 10 лет назад
Родитель
Сommit
84a2c70da2
2 измененных файлов с 57 добавлено и 3 удалено
  1. 9 2
      src/directives/component.js
  2. 48 1
      test/unit/specs/directives/component_spec.js

+ 9 - 2
src/directives/component.js

@@ -117,6 +117,10 @@ module.exports = {
     } else {
       this.resolveComponent(value, _.bind(function () {
         this.unbuild(true)
+        if (this.waitingFor) {
+          this.waitingFor.$destroy()
+          this.waitingFor = null
+        }
         var options
         var self = this
         var waitFor = this.waitForEvent
@@ -124,15 +128,18 @@ module.exports = {
           options = {
             created: function () {
               this.$once(waitFor, function () {
+                self.waitingFor = null
                 self.transition(this, cb)
               })
             }
           }
         }
         var cached = this.getCached()
-        var newComponent = cached || this.build(options)
+        var newComponent = this.build(options)
         if (!waitFor || cached) {
           this.transition(newComponent, cb)
+        } else {
+          this.waitingFor = newComponent
         }
       }, this))
     }
@@ -273,7 +280,6 @@ module.exports = {
   transition: function (target, cb) {
     var self = this
     var current = this.childVM
-    this.unsetCurrent()
     this.setCurrent(target)
     switch (self.transMode) {
       case 'in-out':
@@ -297,6 +303,7 @@ module.exports = {
    */
 
   setCurrent: function (child) {
+    this.unsetCurrent()
     this.childVM = child
     var refID = child._refID || this.refID
     if (refID) {

+ 48 - 1
test/unit/specs/directives/component_spec.js

@@ -312,13 +312,60 @@ if (_.inBrowser) {
         }
       })
       vm.$children[0].$emit('ok')
+      expect(el.textContent).toBe('AAA')
       vm.view = 'view-b'
       _.nextTick(function () {
         expect(el.textContent).toBe('AAA')
         // old vm is already removed, this is the new vm
+        expect(vm.$children.length).toBe(1)
         vm.$children[0].$emit('ok')
         expect(el.textContent).toBe('BBB')
-        done()
+        // ensure switching before ready event correctly
+        // cleans up the component being waited on.
+        // see #1152
+        vm.view = 'view-a'
+        _.nextTick(function () {
+          vm.view = 'view-b'
+          _.nextTick(function () {
+            expect(vm.$children.length).toBe(1)
+            expect(vm.$children[0].$el.textContent).toBe('BBB')
+            done()
+          })
+        })
+      })
+    })
+
+    // #1150
+    it('wait-for + keep-alive', function (done) {
+      var vm = new Vue({
+        el: el,
+        data: {
+          view: 'view-a'
+        },
+        template: '<component is="{{view}}" wait-for="ok" keep-alive></component>',
+        components: {
+          'view-a': {
+            template: 'AAA'
+          },
+          'view-b': {
+            template: 'BBB'
+          }
+        }
+      })
+      vm.$children[0].$emit('ok')
+      expect(el.textContent).toBe('AAA')
+      vm.view = 'view-b'
+      _.nextTick(function () {
+        expect(vm.$children.length).toBe(2)
+        vm.$children[1].$emit('ok')
+        expect(el.textContent).toBe('BBB')
+        vm.view = 'view-a'
+        _.nextTick(function () {
+          // should switch without the need to emit
+          // because of keep-alive
+          expect(el.textContent).toBe('AAA')
+          done()
+        })
       })
     })