From 78f81484af4e33365744e37925501344b1ff309a Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Wed, 20 Jun 2018 14:27:24 +0800 Subject: [PATCH] fix(lifecycle): updated should not be called after component being destroyed, fix #8076 --- src/core/observer/scheduler.js | 2 +- test/unit/features/options/lifecycle.spec.js | 37 ++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/core/observer/scheduler.js b/src/core/observer/scheduler.js index e7ccf57dd25..59c22aff7bf 100644 --- a/src/core/observer/scheduler.js +++ b/src/core/observer/scheduler.js @@ -98,7 +98,7 @@ function callUpdatedHooks (queue) { while (i--) { const watcher = queue[i] const vm = watcher.vm - if (vm._watcher === watcher && vm._isMounted) { + if (vm._watcher === watcher && vm._isMounted && !vm._isDestroyed) { callHook(vm, 'updated') } } diff --git a/test/unit/features/options/lifecycle.spec.js b/test/unit/features/options/lifecycle.spec.js index 3fa152e70c2..ccc9d2106de 100644 --- a/test/unit/features/options/lifecycle.spec.js +++ b/test/unit/features/options/lifecycle.spec.js @@ -199,6 +199,43 @@ describe('Options lifecycle hooks', () => { expect(calls).toEqual(['child', 'parent']) }).then(done) }) + + // #8076 + it('should not be called after destroy', done => { + const updated = jasmine.createSpy('updated') + const destroyed = jasmine.createSpy('destroyed') + + Vue.component('todo', { + template: '
{{todo.done}}
', + props: ['todo'], + destroyed, + updated + }) + + const vm = new Vue({ + template: ` +
+ +
+ `, + data () { + return { + todos: [{ id: 1, done: false }] + } + }, + computed: { + pendingTodos () { + return this.todos.filter(t => !t.done) + } + } + }).$mount() + + vm.todos[0].done = true + waitForUpdate(() => { + expect(destroyed).toHaveBeenCalled() + expect(updated).not.toHaveBeenCalled() + }).then(done) + }) }) describe('beforeDestroy', () => {