diff --git a/src/core/components/keep-alive.js b/src/core/components/keep-alive.js
index 06f6e433..10303d2e 100644
--- a/src/core/components/keep-alive.js
+++ b/src/core/components/keep-alive.js
@@ -1,3 +1,5 @@
+import { callHook } from 'core/instance/lifecycle'
+
export default {
name: 'keep-alive',
_abstract: true,
@@ -20,9 +22,11 @@ export default {
realChild.data.keepAlive = true
return rawChild
},
- beforeDestroy () {
+ destroyed () {
for (const key in this.cache) {
- this.cache[key].child.$destroy()
+ const vnode = this.cache[key]
+ callHook(vnode.child, 'deactivated')
+ vnode.child.$destroy()
}
}
}
diff --git a/src/core/vdom/create-component.js b/src/core/vdom/create-component.js
index 2549cda1..fc1441d7 100644
--- a/src/core/vdom/create-component.js
+++ b/src/core/vdom/create-component.js
@@ -128,10 +128,12 @@ function insert (vnode: MountedComponentVNode) {
}
function destroy (vnode: MountedComponentVNode) {
- if (!vnode.data.keepAlive) {
- vnode.child.$destroy()
- } else {
- callHook(vnode.child, 'deactivated')
+ if (!vnode.child._isDestroyed) {
+ if (!vnode.data.keepAlive) {
+ vnode.child.$destroy()
+ } else {
+ callHook(vnode.child, 'deactivated')
+ }
}
}
diff --git a/src/core/vdom/patch.js b/src/core/vdom/patch.js
index 467b3ff1..fd9da146 100644
--- a/src/core/vdom/patch.js
+++ b/src/core/vdom/patch.js
@@ -126,13 +126,13 @@ export function createPatchFunction (backend) {
if (isDef(data)) {
if (isDef(i = data.hook) && isDef(i = i.destroy)) i(vnode)
for (i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode)
- if (isDef(i = vnode.children)) {
- for (j = 0; j < vnode.children.length; ++j) {
- invokeDestroyHook(vnode.children[j])
- }
- }
- if (isDef(i = vnode.child)) {
- invokeDestroyHook(i._vnode)
+ }
+ if (isDef(i = vnode.child)) {
+ invokeDestroyHook(i._vnode)
+ }
+ if (isDef(i = vnode.children)) {
+ for (j = 0; j < vnode.children.length; ++j) {
+ invokeDestroyHook(vnode.children[j])
}
}
}
diff --git a/test/unit/features/component/component-keep-alive.spec.js b/test/unit/features/component/component-keep-alive.spec.js
index 8b075229..b703d5cb 100644
--- a/test/unit/features/component/component-keep-alive.spec.js
+++ b/test/unit/features/component/component-keep-alive.spec.js
@@ -12,14 +12,16 @@ describe('Component keep-alive', () => {
created: jasmine.createSpy('one created'),
mounted: jasmine.createSpy('one mounted'),
activated: jasmine.createSpy('one activated'),
- deactivated: jasmine.createSpy('one deactivated')
+ deactivated: jasmine.createSpy('one deactivated'),
+ destroyed: jasmine.createSpy('one destroyed')
}
two = {
template: '
two
',
created: jasmine.createSpy('two created'),
mounted: jasmine.createSpy('two mounted'),
activated: jasmine.createSpy('two activated'),
- deactivated: jasmine.createSpy('two deactivated')
+ deactivated: jasmine.createSpy('two deactivated'),
+ destroyed: jasmine.createSpy('two destroyed')
}
components = {
one,
@@ -34,36 +36,43 @@ describe('Component keep-alive', () => {
component.created.calls.count(),
component.mounted.calls.count(),
component.activated.calls.count(),
- component.deactivated.calls.count()
+ component.deactivated.calls.count(),
+ component.destroyed.calls.count()
]).toEqual(callCounts)
}
it('should work', done => {
const vm = new Vue({
- template: '
',
+ template: '
',
data: {
- view: 'one'
+ view: 'one',
+ ok: true
},
components
}).$mount()
expect(vm.$el.textContent).toBe('one')
- assertHookCalls(one, [1, 1, 1, 0])
- assertHookCalls(two, [0, 0, 0, 0])
+ assertHookCalls(one, [1, 1, 1, 0, 0])
+ assertHookCalls(two, [0, 0, 0, 0, 0])
vm.view = 'two'
waitForUpdate(() => {
expect(vm.$el.textContent).toBe('two')
- assertHookCalls(one, [1, 1, 1, 1])
- assertHookCalls(two, [1, 1, 1, 0])
+ assertHookCalls(one, [1, 1, 1, 1, 0])
+ assertHookCalls(two, [1, 1, 1, 0, 0])
vm.view = 'one'
}).then(() => {
expect(vm.$el.textContent).toBe('one')
- assertHookCalls(one, [1, 1, 2, 1])
- assertHookCalls(two, [1, 1, 1, 1])
+ assertHookCalls(one, [1, 1, 2, 1, 0])
+ assertHookCalls(two, [1, 1, 1, 1, 0])
vm.view = 'two'
}).then(() => {
expect(vm.$el.textContent).toBe('two')
- assertHookCalls(one, [1, 1, 2, 2])
- assertHookCalls(two, [1, 1, 2, 1])
+ assertHookCalls(one, [1, 1, 2, 2, 0])
+ assertHookCalls(two, [1, 1, 2, 1, 0])
+ vm.ok = false // teardown
+ }).then(() => {
+ expect(vm.$el.textContent).toBe('')
+ assertHookCalls(one, [1, 1, 2, 3, 1])
+ assertHookCalls(two, [1, 1, 2, 2, 1])
}).then(done)
})
@@ -93,15 +102,15 @@ describe('Component keep-alive', () => {
}
}).$mount(el)
expect(vm.$el.textContent).toBe('one')
- assertHookCalls(one, [1, 1, 1, 0])
- assertHookCalls(two, [0, 0, 0, 0])
+ assertHookCalls(one, [1, 1, 1, 0, 0])
+ assertHookCalls(two, [0, 0, 0, 0, 0])
vm.view = 'two'
waitForUpdate(() => {
expect(vm.$el.innerHTML).toBe(
'one
'
)
- assertHookCalls(one, [1, 1, 1, 1])
- assertHookCalls(two, [0, 0, 0, 0])
+ assertHookCalls(one, [1, 1, 1, 1, 0])
+ assertHookCalls(two, [0, 0, 0, 0, 0])
}).thenWaitFor(nextFrame).then(() => {
expect(vm.$el.innerHTML).toBe(
'one
'
@@ -112,8 +121,8 @@ describe('Component keep-alive', () => {
expect(vm.$el.innerHTML).toBe(
'two
'
)
- assertHookCalls(one, [1, 1, 1, 1])
- assertHookCalls(two, [1, 1, 1, 0])
+ assertHookCalls(one, [1, 1, 1, 1, 0])
+ assertHookCalls(two, [1, 1, 1, 0, 0])
}).thenWaitFor(nextFrame).then(() => {
expect(vm.$el.innerHTML).toBe(
'two
'
@@ -122,16 +131,16 @@ describe('Component keep-alive', () => {
expect(vm.$el.innerHTML).toBe(
'two
'
)
- assertHookCalls(one, [1, 1, 1, 1])
- assertHookCalls(two, [1, 1, 1, 0])
+ assertHookCalls(one, [1, 1, 1, 1, 0])
+ assertHookCalls(two, [1, 1, 1, 0, 0])
}).then(() => {
vm.view = 'one'
}).then(() => {
expect(vm.$el.innerHTML).toBe(
'two
'
)
- assertHookCalls(one, [1, 1, 1, 1])
- assertHookCalls(two, [1, 1, 1, 1])
+ assertHookCalls(one, [1, 1, 1, 1, 0])
+ assertHookCalls(two, [1, 1, 1, 1, 0])
}).thenWaitFor(nextFrame).then(() => {
expect(vm.$el.innerHTML).toBe(
'two
'
@@ -142,8 +151,8 @@ describe('Component keep-alive', () => {
expect(vm.$el.innerHTML).toBe(
'one
'
)
- assertHookCalls(one, [1, 1, 2, 1])
- assertHookCalls(two, [1, 1, 1, 1])
+ assertHookCalls(one, [1, 1, 2, 1, 0])
+ assertHookCalls(two, [1, 1, 1, 1, 0])
}).thenWaitFor(nextFrame).then(() => {
expect(vm.$el.innerHTML).toBe(
'one
'
@@ -152,8 +161,8 @@ describe('Component keep-alive', () => {
expect(vm.$el.innerHTML).toBe(
'one
'
)
- assertHookCalls(one, [1, 1, 2, 1])
- assertHookCalls(two, [1, 1, 1, 1])
+ assertHookCalls(one, [1, 1, 2, 1, 0])
+ assertHookCalls(two, [1, 1, 1, 1, 0])
}).then(done)
})
@@ -182,16 +191,16 @@ describe('Component keep-alive', () => {
}
}).$mount(el)
expect(vm.$el.textContent).toBe('one')
- assertHookCalls(one, [1, 1, 1, 0])
- assertHookCalls(two, [0, 0, 0, 0])
+ assertHookCalls(one, [1, 1, 1, 0, 0])
+ assertHookCalls(two, [0, 0, 0, 0, 0])
vm.view = 'two'
waitForUpdate(() => {
expect(vm.$el.innerHTML).toBe(
'one
' +
'two
'
)
- assertHookCalls(one, [1, 1, 1, 1])
- assertHookCalls(two, [1, 1, 1, 0])
+ assertHookCalls(one, [1, 1, 1, 1, 0])
+ assertHookCalls(two, [1, 1, 1, 0, 0])
}).thenWaitFor(nextFrame).then(() => {
expect(vm.$el.innerHTML).toBe(
'one
' +
@@ -216,8 +225,8 @@ describe('Component keep-alive', () => {
expect(vm.$el.innerHTML).toBe(
'two
'
)
- assertHookCalls(one, [1, 1, 1, 1])
- assertHookCalls(two, [1, 1, 1, 0])
+ assertHookCalls(one, [1, 1, 1, 1, 0])
+ assertHookCalls(two, [1, 1, 1, 0, 0])
}).then(() => {
vm.view = 'one'
}).then(() => {
@@ -225,8 +234,8 @@ describe('Component keep-alive', () => {
'two
' +
'one
'
)
- assertHookCalls(one, [1, 1, 2, 1])
- assertHookCalls(two, [1, 1, 1, 1])
+ assertHookCalls(one, [1, 1, 2, 1, 0])
+ assertHookCalls(two, [1, 1, 1, 1, 0])
}).thenWaitFor(nextFrame).then(() => {
expect(vm.$el.innerHTML).toBe(
'two
' +
@@ -251,8 +260,8 @@ describe('Component keep-alive', () => {
expect(vm.$el.innerHTML).toBe(
'one
'
)
- assertHookCalls(one, [1, 1, 2, 1])
- assertHookCalls(two, [1, 1, 1, 1])
+ assertHookCalls(one, [1, 1, 2, 1, 0])
+ assertHookCalls(two, [1, 1, 1, 1, 0])
}).then(done)
})
}