Skip to content

Commit 84a2c70

Browse files
committed
properly clean up child when switching before wait-for fires (fix vuejs#1152)
1 parent 8600d8a commit 84a2c70

File tree

2 files changed

+57
-3
lines changed

2 files changed

+57
-3
lines changed

src/directives/component.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,22 +117,29 @@ module.exports = {
117117
} else {
118118
this.resolveComponent(value, _.bind(function () {
119119
this.unbuild(true)
120+
if (this.waitingFor) {
121+
this.waitingFor.$destroy()
122+
this.waitingFor = null
123+
}
120124
var options
121125
var self = this
122126
var waitFor = this.waitForEvent
123127
if (waitFor) {
124128
options = {
125129
created: function () {
126130
this.$once(waitFor, function () {
131+
self.waitingFor = null
127132
self.transition(this, cb)
128133
})
129134
}
130135
}
131136
}
132137
var cached = this.getCached()
133-
var newComponent = cached || this.build(options)
138+
var newComponent = this.build(options)
134139
if (!waitFor || cached) {
135140
this.transition(newComponent, cb)
141+
} else {
142+
this.waitingFor = newComponent
136143
}
137144
}, this))
138145
}
@@ -273,7 +280,6 @@ module.exports = {
273280
transition: function (target, cb) {
274281
var self = this
275282
var current = this.childVM
276-
this.unsetCurrent()
277283
this.setCurrent(target)
278284
switch (self.transMode) {
279285
case 'in-out':
@@ -297,6 +303,7 @@ module.exports = {
297303
*/
298304

299305
setCurrent: function (child) {
306+
this.unsetCurrent()
300307
this.childVM = child
301308
var refID = child._refID || this.refID
302309
if (refID) {

test/unit/specs/directives/component_spec.js

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,13 +312,60 @@ if (_.inBrowser) {
312312
}
313313
})
314314
vm.$children[0].$emit('ok')
315+
expect(el.textContent).toBe('AAA')
315316
vm.view = 'view-b'
316317
_.nextTick(function () {
317318
expect(el.textContent).toBe('AAA')
318319
// old vm is already removed, this is the new vm
320+
expect(vm.$children.length).toBe(1)
319321
vm.$children[0].$emit('ok')
320322
expect(el.textContent).toBe('BBB')
321-
done()
323+
// ensure switching before ready event correctly
324+
// cleans up the component being waited on.
325+
// see #1152
326+
vm.view = 'view-a'
327+
_.nextTick(function () {
328+
vm.view = 'view-b'
329+
_.nextTick(function () {
330+
expect(vm.$children.length).toBe(1)
331+
expect(vm.$children[0].$el.textContent).toBe('BBB')
332+
done()
333+
})
334+
})
335+
})
336+
})
337+
338+
// #1150
339+
it('wait-for + keep-alive', function (done) {
340+
var vm = new Vue({
341+
el: el,
342+
data: {
343+
view: 'view-a'
344+
},
345+
template: '<component is="{{view}}" wait-for="ok" keep-alive></component>',
346+
components: {
347+
'view-a': {
348+
template: 'AAA'
349+
},
350+
'view-b': {
351+
template: 'BBB'
352+
}
353+
}
354+
})
355+
vm.$children[0].$emit('ok')
356+
expect(el.textContent).toBe('AAA')
357+
vm.view = 'view-b'
358+
_.nextTick(function () {
359+
expect(vm.$children.length).toBe(2)
360+
vm.$children[1].$emit('ok')
361+
expect(el.textContent).toBe('BBB')
362+
vm.view = 'view-a'
363+
_.nextTick(function () {
364+
// should switch without the need to emit
365+
// because of keep-alive
366+
expect(el.textContent).toBe('AAA')
367+
done()
368+
})
322369
})
323370
})
324371

0 commit comments

Comments
 (0)